From 7788ec532d3730f0a521bb0634a25da12b5bc081 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 31 Jul 2022 15:21:35 +0200 Subject: Improve C++20 modules support --- xmake/core/project/target.lua | 106 ++++++ xmake/languages/c++/load.lua | 1 + xmake/languages/objc++/load.lua | 1 + xmake/rules/c++/modules/build_modules/clang.lua | 246 ++++++++----- xmake/rules/c++/modules/build_modules/common.lua | 409 +++++++++++++++++++++ xmake/rules/c++/modules/build_modules/gcc.lua | 228 ++++++++++-- .../c++/modules/build_modules/module_parser.lua | 149 -------- xmake/rules/c++/modules/build_modules/msvc.lua | 267 +++++++++----- xmake/rules/c++/modules/xmake.lua | 148 +++++++- xmake/rules/qt/qmltyperegistrar/xmake.lua | 4 +- 10 files changed, 1170 insertions(+), 389 deletions(-) create mode 100644 xmake/rules/c++/modules/build_modules/common.lua delete mode 100644 xmake/rules/c++/modules/build_modules/module_parser.lua diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index b00cbe15a..26223258c 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1566,6 +1566,110 @@ function _instance:headerfiles(outputdir, opt) return srcheaders, dstheaders end +-- get the module files +function _instance:modulefiles(outputdir) + local modules = self:get("modulefiles") + + -- get the installed module directory + local moduledir = outputdir + if not moduledir and self:installdir() then + path.join(self:installdir(), "include") + end + + -- get the extra information + local extrainfo = table.wrap(self:get("__extra_modulefiles")) + + -- get the source paths and destinate paths + local srcmodules = {} + local dstmodules = {} + local srcmodules_removed = {} + local removed_count = 0 + for _, module in ipairs(table.wrap(modules)) do + -- mark as removed files? + local removed = false + local prefix = "__remove_" + if module:startswith(prefix) then + module = module:sub(#prefix + 1) + removed = true + end + + -- get the root directory + local rootdir, count = module:gsub("|.*$", ""):gsub("%(.*%)$", "") + if count == 0 then + rootdir = nil + end + if rootdir and rootdir:trim() == "" then + rootdir = "." + end + + -- remove '(' and ')' first + local srcpaths = module:gsub("[%(%)]", "") + if srcpaths then + + -- get the source paths + srcpaths = os.match(srcpaths) + if srcpaths then + if removed then + removed_count = removed_count + #srcpaths + table.join2(srcmodules_removed, srcpaths) + else + -- add the source modules + table.join2(srcmodules, srcpaths) + + -- get the destinate directories if the install directory exists + if moduledir then + local prefixdir = (extrainfo[module] or {}).prefixdir + for _, srcpath in ipairs(srcpaths) do + local dstdir = moduledir + if prefixdir then + dstdir = path.join(dstdir, prefixdir) + end + local dstmodule = nil + if rootdir then + dstmodule = path.absolute(path.relative(srcpath, rootdir), dstdir) + else + dstmodule = path.join(dstdir, path.filename(srcpath)) + end + table.insert(dstmodules, dstmodule) + end + end + end + end + end + end + + -- remove all module files which need be removed + if removed_count > 0 then + table.remove_if(srcmodules, function (i, srcmodule) + for _, removed_file in ipairs(srcmodules_removed) do + local pattern = path.translate(removed_file:gsub("|.*$", "")) + if pattern:sub(1, 2):find('%.[/\\]') then + pattern = pattern:sub(3) + end + pattern = path.pattern(pattern) + if srcmodule:match(pattern) then + if i <= #dstmodules then + table.remove(dstmodules, i) + end + return true + end + end + end) + end + + return srcmodules, dstmodules +end + +-- get the bmi files +function _instance:bmifiles(outputdir) + local compilerinst = self:compiler() + + -- get the installed bmi directory + local bmidir = bmi_outputdir or path.join(self:installdir(), "lib", compilerinst:name() + "-" + compilerinst:version()) + + return self:_copiedfiles("bmifiles", bmidir) +end + -- get the configuration files function _instance:configfiles(outputdir) return self:_copiedfiles("configfiles", outputdir or self:configdir(), function (dstpath, fileinfo) @@ -2145,6 +2249,7 @@ function target.apis() , "target.set_rundir" -- target.add_xxx , "target.add_files" + , "target.add_modulefiles" , "target.add_cleanfiles" , "target.add_configfiles" , "target.add_installfiles" @@ -2153,6 +2258,7 @@ function target.apis() -- target.remove_xxx , "target.remove_files" , "target.remove_headerfiles" + , "target.remove_modulefiles" } , dictionary = { diff --git a/xmake/languages/c++/load.lua b/xmake/languages/c++/load.lua index 16380ab3c..b3c2b2ae3 100644 --- a/xmake/languages/c++/load.lua +++ b/xmake/languages/c++/load.lua @@ -224,6 +224,7 @@ function _get_apis() -- target.add_xxx , "target.add_headers" -- TODO deprecated , "target.add_headerfiles" + , "target.add_modulefiles" , "target.add_linkdirs" , "target.add_includedirs" , "target.add_sysincludedirs" diff --git a/xmake/languages/objc++/load.lua b/xmake/languages/objc++/load.lua index 85df22850..2950a28f6 100644 --- a/xmake/languages/objc++/load.lua +++ b/xmake/languages/objc++/load.lua @@ -80,6 +80,7 @@ function _get_apis() -- target.add_xxx , "target.add_headers" -- TODO deprecated , "target.add_headerfiles" + , "target.add_modulefiles" , "target.add_linkdirs" , "target.add_includedirs" , "target.add_sysincludedirs" diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua index 120e1d5d0..bce008766 100644 --- a/xmake/rules/c++/modules/build_modules/clang.lua +++ b/xmake/rules/c++/modules/build_modules/clang.lua @@ -20,109 +20,191 @@ -- imports import("core.tool.compiler") +import("core.project.project") +import("core.project.depend") +import("core.base.json") import("core.project.config") +import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) -import("module_parser") + +local default_flags = { "-std=c++20" } -- load parent target with modules files function load_parent(target, opt) - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules") then - modulesflag = "-fmodules" - elseif compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(clang): does not support c++ module!") + local common = import("common") + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) -- add module flags - target:add("cxxflags", modulesflag) + target:add("cxxflags", "-fmodules") -- add the module cache directory - local cachedir = path.join(config.buildir(), ".gens", "rules", "modules", "cache") - target:add("cxxflags", "-fmodules-cache-path=" .. cachedir, {force = true}) - target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) + target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", {force = true}) + target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, "-fprebuilt-module-path=" .. stlcachedir, {force = true}) + + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.get_cache_dir(dep) + dep:add("cxxflags", "-fmodules") + dep:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", {force = true}) + target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, "-fprebuilt-module-path=" .. stlcachedir, {force = true}) + target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, {force = true}) + end end --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - - -- get modules flag +-- check C++20 module support +function check_module_support(target) local modulesflag local compinst = compiler.load("cxx", {target = target}) if compinst:has_flags("-fmodules") then modulesflag = "-fmodules" - elseif compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" end assert(modulesflag, "compiler(clang): does not support c++ module!") - -- get the module cache directory, @note we must use same cache directory for each targets - -- @see https://github.com/xmake-io/xmake/issues/2194 - -- - local cachedir = path.join(config.buildir(), ".gens", "rules", "modules", "cache") - - -- we need patch objectfiles to sourcebatch for linking module objects - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + target:data_set("cxx.has_p1689r4", false) +end + +function generate_dependencies(target, sourcebatch, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function() + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + + if target:data("cxx.has_p1689r4") then + else -- fallback as clang doesn't support p1689r4 + local dependinfo = common.fallback_generate_dependencies(target, jsonfile, sourcefile) + local jsondata = json.encode(dependinfo) + + io.writefile(jsonfile, jsondata) + end + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) end +end + +-- generate target header units +function generate_headerunits(target, batchcmds, sourcebatch, opt) + local common = import("common") + + local compinst = target:compiler("cxx") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + -- build headerunits + local objectfiles = {} + local public_flags = {} + local private_flags = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. ".pcm" + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = { "-fmodules-cache-path=" .. cachedir, "-emit-module", "-c", "-o", bmifile } + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path }) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + end + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.append(public_flags, "-fmodule-file=" .. bmifile) + else + local bmifile = path.join(stlcachedir, headerunit.name .. ".pcm") + + if not os.isfile(bmifile) then + local args = { "-fmodules-cache-path=" .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path } + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) - -- load moduledeps - local moduledeps, moduledeps_files = module_parser.load(target, sourcebatch, opt) - - -- compile module files to object files - local count = 0 - local modulefiles = {} - local sourcefiles_total = #sourcebatch.sourcefiles - for i = 1, sourcefiles_total do - local sourcefile = sourcebatch.sourcefiles[i] - local moduleinfo = moduledeps_files[sourcefile] or {} - - -- make module file path, @note we need process submodule name, e.g. module.submodule.mpp -> module.submodule.pcm - -- @see https://github.com/xmake-io/xmake/pull/1982 - local modulefile = path.join(cachedir, (moduleinfo.name or path.basename(sourcefile)) .. ".pcm") - table.insert(modulefiles, modulefile) - - -- make build job - moduleinfo.job = batchjobs:newjob(sourcefile, function (index, total) - - -- compile module files to *.pcm - local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, - "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = modulefiles[i] - opt2.dependfile = target:dependfile(opt2.objectfile) - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - - -- compile *.pcm to object files - opt2.configs = {force = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}}} - opt2.quiet = true - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - objectbuilder.build_object(target, modulefiles[i], opt2) - - -- add module flags to other c++ files after building all modules - count = count + 1 - if count == sourcefiles_total then - target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir, {force = true}) - -- FIXME It is invalid for the module implementation unit - --target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "-fmodule-file=" .. modulefile, {force = true}) - end end - end) + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.append(private_flags, "-fmodule-file=" .. bmifile) + end + end + + return public_flags, private_flags +end + +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") + + -- append deps modules + local flags = {} + for _, dep in ipairs(target:orderdeps()) do + table.join2(flags, dep:data("cxx.modules.flags")) end + flags = table.unique(flags) + target:add("cxxflags", flags, {force = true, expand = false}) + + local common_args = { "-fmodules-cache-path=" .. cachedir, "-emit-module-interface" } + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end - -- build batchjobs - module_parser.build_batchjobs(moduledeps, batchjobs, opt.rootjob) + local args = { } + local flag = {} + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.join2(flag, { "-fmodule-file=" .. bmifile }) + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args)) + + target:add("cxxflags", flag, {public = true, force = true}) + for _, f in ipairs(flag) do + target:data_add("cxx.modules.flags", f) + end + end + end end diff --git a/xmake/rules/c++/modules/build_modules/common.lua b/xmake/rules/c++/modules/build_modules/common.lua new file mode 100644 index 000000000..bf64386e4 --- /dev/null +++ b/xmake/rules/c++/modules/build_modules/common.lua @@ -0,0 +1,409 @@ +import("core.base.json") +import("core.project.config") +import("core.tool.compiler") +import("core.cache.globalcache") +import("core.project.project") +import("lib.detect") +import("lib.detect.find_package") +import("lib.detect.find_file") + +local stl_headers = { + "algorithm", + "forward_list", + "numbers", + "stop_token", + "any", + "fstream", + "numeric", + "streambuf", + "array", + "functional", + "optional", + "string", + "atomic", + "future", + "ostream", + "string_view", + "barrier", + "initializer_list", + "queue", + "bit", + "iomanip", + "random", + "syncstream", + "bitset", + "ios", + "ranges", + "system_error", + "charconv", + "iosfwd", + "ratio", + "thread", + "chrono", + "iostream", + "regex", + "tuple", + "codecvt", + "istream", + "scoped_allocator", + "typeindex", + "compare", + "iterator", + "semaphore", + "typeinfo", + "complex", + "latch", + "set", + "type_traits", + "concepts", + "limits", + "shared_mutex", + "unordered_map", + "condition_variable", + "list", + "source_location", + "unordered_set", + "coroutine", + "locale", + "span", + "utility", + "deque", + "map", + "spanstream", + "valarray", + "exception", + "memory", + "sstream", + "variant", + "execution", + "memory_resource", + "stack", + "vector", + "filesystem", + "mutex", + "version", + "format", + "new", + "type_traits", + "string_view", + "stdexcept"} + +function get_stl_headers() + return stl_headers +end + +function is_stl_header(header) + for _, stl_header in ipairs(stl_headers) do + if stl_header == header then + return true + end + end + + return false +end + +function get_stlcache_dir(target) + local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") + if target:has_tool("cxx", "clang", "clangxx") then + stlcachedir = path.join(config.buildir(), "stlmodules", "cache") + end + if not os.isdir(stlcachedir) then + os.mkdir(stlcachedir) + end + + return stlcachedir +end + +function get_cache_dir(target) + local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + if not os.isdir(cachedir) then + os.mkdir(cachedir) + end + + return cachedir +end + +function patch_sourcebatch(target, sourcebatch, opt) + local cachedir = get_cache_dir(target) + + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + local dependfile = target:dependfile(objectfile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, dependfile) + end + +end + +function get_bmi_ext(target) + if target:has_tool("cxx", "gcc", "gxx") then + return ".gcm" + elseif target:has_tool("cxx", "cl") then + return ".ifc" + elseif target:has_tool("cxx", "clang", "clangxx") then + return ".pcm" + end + + assert(false) +end + +function load(target, sourcebatch, opt) + local cachedir = get_cache_dir(target) + + local moduleinfos + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + if os.isfile(dependfile) then + local data = io.load(dependfile) + + if data then + moduleinfos = moduleinfos or {} + + local moduleinfo = json.decode(data.moduleinfo) + moduleinfo.sourcefile = sourcefile + if moduleinfo then + table.append(moduleinfos, moduleinfo) + end + end + end + end + + return moduleinfos +end + +function parse_dependency_data(target, moduleinfos, opt) + local cachedir = get_cache_dir(target) + + local modules + for _, moduleinfo in ipairs(moduleinfos) do + assert(moduleinfo.version <= 1) + for _, rule in ipairs(moduleinfo.rules) do + modules = modules or {} + + local m = {} + + for _, provide in ipairs(rule.provides) do + m.provides = m.provides or {} + + if provide["compiled-module-path"] then + if not path.is_absolute(provide["compiled-module-path"]) then + m.provides[provide["logical-name"] ] = path.absolute(provide["compiled-module-path"]) + else + m.provides[provide["logical-name"] ] = provide["compiled-module-path"] + end + else -- assume path with name + local name = provide["logical-name"] .. get_bmi_ext(target) + name:replace(":", "-") + + m.provides[provide["logical-name"] ] = { + bmi = path.join(cachedir, name), + sourcefile = moduleinfo.sourcefile + } + end + end + + modules[rule["primary-output"] ] = m + end + end + + for _, moduleinfo in ipairs(moduleinfos) do + for _, rule in ipairs(moduleinfo.rules) do + local m = modules[rule["primary-output"] ] + for _, r in ipairs(rule.requires) do + m.requires = m.requires or {} + + local p = r["source-path"] + if not p then + for _, dependency in pairs(modules) do + if dependency.provides and dependency.provides[r["logical-name"] ] then + p = dependency.provides[r["logical-name"] ].bmi + break + end + end + end + + m.requires[r["logical-name"] ] = { + method = r["lookup-method"] or "by-name", + path = p, + unique = r["unique-on-source-path"] or false + } + end + end + end + + return modules +end + +function _topological_sort_visit(node, nodes, modules, output) + if node.marked then + return + end + + assert(not node.tempmarked) + + node.tempmarked = true + + local m1 = modules[node.objectfile] + + assert(m1.provides) + for _, n in ipairs(nodes) do + if not n.tempmarked then + local m2 = modules[n.objectfile] + + for name, provide in pairs(m1.provides) do + if m2.requires and m2.requires[name] then + _topological_sort_visit(n, nodes, modules, output) + end + end + end + end + + node.tempmarked = false + node.marked = true + + table.insert(output, 1, node.objectfile) +end + +function _topological_sort_has_node_without_mark(nodes) + for _, node in ipairs(nodes) do + if not node.marked then + return true + end + end + + return false +end + +function _topological_sort_get_first_unmarked_node(nodes) + for _, node in ipairs(nodes) do + if not node.marked and not node.tempmarked then + return node + end + end +end + +function sort_modules_by_dependencies(objectfiles, modules) + local output = {} + + local nodes = {} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m.provides then + table.append(nodes, { marked = false, tempmarked = false, objectfile = objectfile }) + end + end + + while _topological_sort_has_node_without_mark(nodes) do + local node = _topological_sort_get_first_unmarked_node(nodes) + + _topological_sort_visit(node, nodes, modules, output) + end + + return output +end + +function find_quote_header_file(target, sourcefile, file) + local p = path.join(path.directory(path.absolute(sourcefile, project.directory())), file) + + assert(os.isfile(p)) + + return p +end + +function find_angle_header_file(target, file) + -- check if the header is in subtarget + + local headerpaths = {} + + for _, dep in ipairs(target:orderdeps()) do + table.append(headerpaths, dep:scriptdir()) + end + + if project.required_packages then + for _, name in ipairs(target:get("packages")) do + local package = project.required_package(name) + table.join2(headerpaths, package:get("sysincludedirs")) + end + end + + table.join2(headerpaths, target:get("includedirs")) + + local p = find_file(file, table.join(headerpaths, { "/usr/include/**", "/usr/local/include/**" })) + + assert(os.isfile(p)) + + return p +end + +function fallback_generate_dependencies(target, jsonfile, sourcefile) + local output = { + version = 0, + revision = 0, + rules = {} + } + + local rule = { + outputs = { + jsonfile + } + } + rule["primary-output"] = target:objectfile(sourcefile) + + local module_name + local module_deps = {} + local sourcecode = io.readfile(sourcefile) + sourcecode = sourcecode:gsub("//.-\n", "\n") + sourcecode = sourcecode:gsub("/%*.-%*/", "") + for _, line in ipairs(sourcecode:split("\n", {plain = true})) do + if not module_name then + module_name = line:match("export%s+module%s+(.+)%s*;") + end + + local module_depname = line:match("import%s+(.+)%s*;") + + if module_depname then + local module_dep = {} + + -- partition? import :xxx; + if module_depname:startswith(":") then + module_depname = module_name .. module_depname + elseif module_depname:startswith("\"") then + module_depname = module_depname:sub(2, -2) + module_dep["lookup-method"] = "include-quote" + module_dep["unique-on-source-path"] = true + module_dep["source-path"] = find_quote_header_file(target, sourcefile, module_depname) + elseif module_depname:startswith("<") then + module_depname = module_depname:sub(2, -2) + module_dep["lookup-method"] = "include-angle" + module_dep["unique-on-source-path"] = true + module_dep["source-path"] = find_angle_header_file(target, module_depname) + end + + module_dep["logical-name"] = module_depname + + table.insert(module_deps, module_dep) + end + end + + if module_name then + table.append(rule.outputs, module_name .. get_bmi_ext(target)) + + local provide = {} + provide["logical-name"] = module_name + provide["source-path"] = path.absolute(sourcefile, project.directory()) + + rule.provides = {} + table.append(rule.provides, provide) + end + + rule.requires = module_deps + + table.append(output.rules, rule) + + return output +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua index 3bf8b8fcc..97bb9cc9a 100644 --- a/xmake/rules/c++/modules/build_modules/gcc.lua +++ b/xmake/rules/c++/modules/build_modules/gcc.lua @@ -20,27 +20,58 @@ -- imports import("core.tool.compiler") +import("core.project.project") +import("core.project.depend") +import("core.base.json") +import("core.project.config") +import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) -import("module_parser") + +local default_flags = {"-std=c++20"} + +function get_module_mapper() + local mapper_file = path.join(config.buildir(), "mapper.txt") + if not os.isfile(mapper_file) then + io.writefile(mapper_file, "") + end + + return mapper_file +end + +function add_module_to_mapper(file, module, bmi) + for line in io.lines(file) do + if line:startswith(module .. " ") then + return false + end + end + + local f = io.open(file, "a") + f:printf("%s %s\n", module, bmi) + f:close() + + return true +end -- load parent target with modules files function load_parent(target, opt) - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" + local common = import("common") + local cachedir = common.get_cache_dir(target) + + target:add("cxxflags", "-fmodules-ts") + if os.isfile(get_module_mapper()) then + os.rm(get_module_mapper()) end - assert(modulesflag, "compiler(gcc): does not support c++ module!") + target:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) - -- add module flags - target:add("cxxflags", modulesflag) + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.get_cache_dir(dep) + dep:add("cxxflags", "-fmodules-ts") + dep:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) + end end --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - - -- get modules flag +-- check C++20 module support +function check_module_support(target) local modulesflag local compinst = compiler.load("cxx", {target = target}) if compinst:has_flags("-fmodules-ts") then @@ -48,37 +79,154 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) end assert(modulesflag, "compiler(gcc): does not support c++ module!") - -- we need patch objectfiles to sourcebatch for linking module objects - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + if compinst:has_flags("-fdep-format=trtbd") then + target:data_set("cxx.has_p1689r4", true) + end +end + +function generate_dependencies(target, sourcebatch, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + local compinst = target:compiler("cxx") + local common_args = {"-E", "-x", "c++"} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function() + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + + if target:data("cxx.has_p1689r4") then + local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) + local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) + + local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, "-fdep-file=" .. jsonfile, "-fdep-format=trtbd", "-fdep-output=" .. target:objectfile(sourcefile), "-o", ifile} + + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) + else -- fallback as GCC doesn't fully support p1689r4 + local dependinfo = common.fallback_generate_dependencies(target, jsonfile, sourcefile) + local jsondata = json.encode(dependinfo) + + io.writefile(jsonfile, jsondata) + end + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) end +end + +-- generate target header units +function generate_headerunits(target, batchcmds, sourcebatch, opt) + local common = import("common") + + local compinst = target:compiler("cxx") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + local mapper_file = get_module_mapper() + + -- build headerunits + local objectfiles = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. ".gcm" + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + local args = { "-c" } + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) + add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) + end + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + else + local bmifile = path.join(stlcachedir, headerunit.name .. ".gcm") + + if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if not os.isfile(bmifile) then + local args = { "-c", "-x", "c++-system-header", headerunit.name } + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + end + end - -- load moduledeps - local moduledeps, moduledeps_files = module_parser.load(target, sourcebatch, opt) - - -- compile module files to object files - for i = 1, #sourcebatch.sourcefiles do - local sourcefile = sourcebatch.sourcefiles[i] - local moduleinfo = assert(moduledeps_files[sourcefile], "moduleinfo(%s) not found!", sourcefile) - moduleinfo.job = batchjobs:newjob(sourcefile, function (index, total) - local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - end) end +end + +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") - -- add module flags - target:add("cxxflags", modulesflag) + local mapper_file = get_module_mapper() + local common_args = { "-x", "c++" } + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] - -- build batchjobs - module_parser.build_batchjobs(moduledeps, batchjobs, opt.rootjob) + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = { "-o", objectfile } + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + if add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then + table.join2(args, { "-c", provide.sourcefile }) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args)) + + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + target:add("objectfiles", objectfile) + end + end end diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua deleted file mode 100644 index 91a09aadb..000000000 --- a/xmake/rules/c++/modules/build_modules/module_parser.lua +++ /dev/null @@ -1,149 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file module_parser.lua --- - --- imports -import("core.project.depend") -import("core.base.hashset") - --- get depend file of module source file -function _get_dependfile_of_modulesource(target, sourcefile) - return target:dependfile(sourcefile) -end - --- get depend file of module object file, compiler will rewrite it -function _get_dependfile_of_moduleobject(target, sourcefile) - local objectfile = target:objectfile(sourcefile) - return target:dependfile(objectfile) -end - --- generate module deps for the given file -function _generate_moduledeps(target, sourcefile, opt) - local dependfile = _get_dependfile_of_modulesource(target, sourcefile) - depend.on_changed(function () - - -- trace - vprint("generating.moduledeps %s", sourcefile) - - -- generating deps - local module_name - local module_deps - local sourcecode = io.readfile(sourcefile) - sourcecode = sourcecode:gsub("//.-\n", "\n") - sourcecode = sourcecode:gsub("/%*.-%*/", "") - for _, line in ipairs(sourcecode:split("\n", {plain = true})) do - if not module_name then - module_name = line:match("export%s+module%s+(.+)%s*;") - end - local module_depname = line:match("import%s+(.+)%s*;") - if module_depname then - -- partition? import :xxx; - if module_depname:startswith(":") then - module_depname = module_name .. module_depname - end - module_deps = module_deps or {} - table.insert(module_deps, module_depname) - end - end - - -- save depend data - if module_name then - local dependinfo = {moduleinfo = {name = module_name, deps = module_deps, file = sourcefile}} - return dependinfo - end - - end, {dependfile = dependfile, files = {sourcefile}}) -end - --- build batch jobs with deps -function _build_batchjobs_with_deps(moduledeps, batchjobs, rootjob, jobrefs, moduleinfo) - local targetjob_ref = jobrefs[moduleinfo.name] - if targetjob_ref then - batchjobs:add(targetjob_ref, rootjob) - else - local modulejob = batchjobs:add(moduleinfo.job, rootjob) - if modulejob then - jobrefs[moduleinfo.name] = modulejob - for _, depname in ipairs(moduleinfo.deps) do - local dep = moduledeps[depname] - if dep then -- maybe nil, e.g. `import ;` - _build_batchjobs_with_deps(moduledeps, batchjobs, modulejob, jobrefs, dep) - end - end - end - end -end - --- generate module deps -function generate(target, sourcebatch, opt) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - _generate_moduledeps(target, sourcefile, opt) - end -end - --- load module deps -function load(target, sourcebatch, opt) - - -- do generate first - generate(target, sourcebatch, opt) - - -- load deps - local moduledeps - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local dependfile = _get_dependfile_of_modulesource(target, sourcefile) - if os.isfile(dependfile) then - local data = io.load(dependfile) - if data then - local moduleinfo = data.moduleinfo - if moduleinfo then - moduledeps = moduledeps or {} - moduledeps[moduleinfo.name] = moduleinfo - end - end - end - end - - -- get moduledeps with file map - local moduledeps_files = {} - for _, moduleinfo in pairs(moduledeps) do - moduledeps_files[moduleinfo.file] = moduleinfo - end - return moduledeps, moduledeps_files -end - --- build batch jobs -function build_batchjobs(moduledeps, batchjobs, rootjob) - local depset = hashset.new() - for _, moduleinfo in pairs(moduledeps) do - assert(moduleinfo.job) - for _, depname in ipairs(moduleinfo.deps) do - depset:insert(depname) - end - end - local moduledeps_root = {} - for _, moduleinfo in pairs(moduledeps) do - if not depset:has(moduleinfo.name) then - table.insert(moduledeps_root, moduleinfo) - end - end - local jobrefs = {} - for _, moduleinfo in pairs(moduledeps_root) do - _build_batchjobs_with_deps(moduledeps, batchjobs, rootjob, jobrefs, moduleinfo) - end -end diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 0a8976468..ac1386a27 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -20,57 +20,59 @@ -- imports import("core.tool.compiler") +import("core.project.depend") +import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) -import("module_parser") + +local default_flags = {"/EHsc", "/nologo", "/std:c++20", "/experimental:module"} -- load parent target with modules files function load_parent(target, opt) - + local common = import("common") -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("/experimental:module", "cxxflags") then - modulesflag = "/experimental:module" - end - assert(modulesflag, "compiler(msvc): does not support c++ module!") + local compinst = target:compiler("cxx") -- add module flags - target:add("cxxflags", modulesflag) + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) - -- get output flag - if compinst:has_flags("/ifcOutput", "cxxflags") then - for _, dep in ipairs(target:orderdeps()) do - local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then - local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache") - target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) + target:add("cxxflags", "/experimental:module") + target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) + target:add("cxxflags", {"/ifcSearchDir", stlcachedir}, {force = true, expand = false}) + + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.get_cache_dir(dep) + dep:add("cxxflags", "/experimental:module") + target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) + end + + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") + if os.isdir(stdifcdir) then + target:add("cxxflags", {"/stdIfcDir", winos.short_path(stdifcdir)}, {force = true, expand = false}) + end end + break end end end --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) +-- check C++20 module support +function check_module_support(target) + local compinst = target:compiler("cxx") - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) if compinst:has_flags("/experimental:module", "cxxflags") then modulesflag = "/experimental:module" end assert(modulesflag, "compiler(msvc): does not support c++ module!") -- get output flag - local cachedir local outputflag if compinst:has_flags("/ifcOutput", "cxxflags") then outputflag = "/ifcOutput" - cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - if not os.isdir(cachedir) then - os.mkdir(cachedir) - end - elseif compinst:has_flags("/module:output", "cxxflags") then - outputflag = "/module:output" end assert(outputflag, "compiler(msvc): does not support c++ module!") @@ -78,8 +80,6 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) local interfaceflag if compinst:has_flags("/interface", "cxxflags") then interfaceflag = "/interface" - elseif compinst:has_flags("/module:interface", "cxxflags") then - interfaceflag = "/module:interface" end assert(interfaceflag, "compiler(msvc): does not support c++ module!") @@ -87,8 +87,6 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) local referenceflag if compinst:has_flags("/reference", "cxxflags") then referenceflag = "/reference" - elseif compinst:has_flags("/module:interface", "cxxflags") then - referenceflag = "/module:reference" end assert(referenceflag, "compiler(msvc): does not support c++ module!") @@ -96,83 +94,156 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) local stdifcdirflag if compinst:has_flags("/stdIfcDir", "cxxflags") then stdifcdirflag = "/stdIfcDir" - elseif compinst:has_flags("/module:stdIfcDir", "cxxflags") then - stdifcdirflag = "/module:stdIfcDir" end assert(stdifcdirflag, "compiler(msvc): does not support c++ module!") +end - -- we need patch objectfiles to sourcebatch for linking module objects - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - local dependfile = target:dependfile(objectfile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, dependfile) - end - -- load moduledeps - local moduledeps, moduledeps_files = module_parser.load(target, sourcebatch, opt) - - -- get modulefiles - local modulefiles = {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local moduleinfo = moduledeps_files[sourcefile] or {} - -- make module file path, @note we need process submodule name, e.g. module.submodule.mpp -> module.submodule.ifc - -- @see https://github.com/xmake-io/xmake/issues/2614 - local modulefile = (cachedir and path.join(cachedir, moduleinfo.name or path.basename(sourcefile)) or objectfile) .. ".ifc" - table.insert(modulefiles, modulefile) - end +-- generate dependency files +function generate_dependencies(target, sourcebatch, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") - -- compile module files to object files - local count = 0 - local sourcefiles_total = #sourcebatch.sourcefiles - for i = 1, sourcefiles_total do - local sourcefile = sourcebatch.sourcefiles[i] - local moduleinfo = assert(moduledeps_files[sourcefile], "moduleinfo(%s) not found!", sourcefile) - moduleinfo.job = batchjobs:newjob(sourcefile, function (index, total) - local opt2 = table.join(opt, {configs = {force = {cxxflags = { - interfaceflag, - {outputflag, modulefiles[i]}, - "/TP"}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - - -- add module flags to other c++ files after building all modules - count = count + 1 - if count == sourcefiles_total and not cachedir then - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", {referenceflag, modulefile}, {force = true, expand = false}) - end + local common = import("common") + local cachedir = common.get_cache_dir(target) + local common_args = {"/TP", "/scanDependencies"} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + 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()))) + if not os.isdir(outdir) then + os.mkdir(outdir) end - end) - end - -- add module flags - target:add("cxxflags", modulesflag) - if cachedir then - target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) + local jsonfile = path.join(outdir, path.filename(sourcefile) .. ".json") + local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} + + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) end - if stdifcdirflag then - for _, toolchain_inst in ipairs(target:toolchains()) do - if toolchain_inst:name() == "msvc" then - local vcvars = toolchain_inst:config("vcvars") - if vcvars.VCInstallDir and vcvars.VCToolsVersion then - local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") - if os.isdir(stdifcdir) then - target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false}) - end - end - break +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") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + -- build headerunits + local common_args = {"/TP", "/exportHeader", "/c"} + local objectfiles = {} + local public_flags = {} + local private_flags = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. ".ifc" + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) end + + local args = {"/headerName" .. headerunit.type, headerunit.path, "/ifcOutput", outdir, "/Fo" .. objectfile} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + local flag = {"/headerUnit" .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} + table.join2(public_flags, flag) + target:add("objectfiles", objectfile) + else + local bmifile = path.join(stlcachedir, headerunit.name .. ".ifc") + local args = {"/exportHeader", "/headerName:angle", headerunit.name, "/ifcOutput", stlcachedir} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args), {envs = vcvars}) + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + local flag = {"/headerUnit:angle", headerunit.name .. "=" .. headerunit.name .. ".ifc"} + table.join2(private_flags, flag) end end - -- build batchjobs - module_parser.build_batchjobs(moduledeps, batchjobs, opt.rootjob) + return public_flags, private_flags end +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + + -- 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 = {"/TP"} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = {"/c", "/Fo" .. objectfile} + + local flag = {} + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + table.join2(args, {"/interface", "/ifcOutput", bmifile, provide.sourcefile}) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + flag = {"/reference", name .. "=" .. path.filename(bmifile)} + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args, bmi_args), {envs = vcvars}) + + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + target:add("cxxflags", flag, {force = true, expand = false}) + for _, f in ipairs(flag) do + target:data_add("cxx.modules.flags", f) + end + target:add("objectfiles", objectfile) + end + end +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 12132da54..0f03b9b13 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -20,46 +20,158 @@ -- define rule: c++.build.modules rule("c++.build.modules") - set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + add_deps("c++.build.modules.builder") + on_config(function (target) - -- we disable to build across targets in parallel, because the source files may depend on other target modules - -- @see https://github.com/xmake-io/xmake/issues/1858 - local target_with_modules + local target_with_modules = (target:modulefiles() and #target:modulefiles() > 0) and true or false + for _, dep in ipairs(target:orderdeps()) do - local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then + local modulefiles = dep:get("modulefiles") + if modulefiles and #modulefiles > 0 then target_with_modules = true break end end + if target_with_modules then - -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, - -- even if some sub-targets do not contain C++ modules. - -- - -- maybe we will have a more fine-grained configuration strategy to disable it in the future. target:set("policy", "build.across_targets_in_parallel", false) + + -- import build_modules + local build_modules if target:has_tool("cxx", "clang", "clangxx") then - import("build_modules.clang").load_parent(target, opt) + build_modules = import("build_modules.clang") elseif target:has_tool("cxx", "gcc", "gxx") then - import("build_modules.gcc").load_parent(target, opt) + build_modules = import("build_modules.gcc") elseif target:has_tool("cxx", "cl") then - import("build_modules.msvc").load_parent(target, opt) + build_modules = import("build_modules.msvc") else local _, toolname = target:tool("cxx") raise("compiler(%s): does not support c++ module!", toolname) end + + -- check C++20 module support + build_modules.check_module_support(target) + + -- load parent + build_modules.load_parent(target, opt) + + for _, modulefile in ipairs(target:modulefiles()) do + target:add("files", modulefile) + end + + target:set("cxx.has_modules", true) + end + end) + + before_build(function(target, opt) + if not target:get("cxx.has_modules") then + return + end + + local build_modules + if target:has_tool("cxx", "clang", "clangxx") then + build_modules = import("build_modules.clang") + elseif target:has_tool("cxx", "gcc", "gxx") then + build_modules = import("build_modules.gcc") + elseif target:has_tool("cxx", "cl") then + build_modules = import("build_modules.msvc") + else + local _, toolname = target:tool("cxx") + raise("compiler(%s): does not support c++ module!", toolname) + end + + -- build dependency data + local common = import("build_modules.common") + + local moduleinfos = {} + for _, sourcebatch in pairs(target:sourcebatches()) do + local batch = sourcebatch + + if batch.rulename == "c++.build.modules.builder" then + batch.objectfiles = {} + batch.dependfiles = {} + common.patch_sourcebatch(target, batch, opt) + end + + if batch.rulename:startswith("c++.build") then + build_modules.generate_dependencies(target, batch, opt) + local infos = common.load(target, batch, opt) + + table.join2(moduleinfos, infos or {}) + end end + + local modules = common.parse_dependency_data(target, moduleinfos, opt) + + target:data_set("cxx.modules", modules) end) - before_build_files(function (target, batchjobs, sourcebatch, opt) + + +rule("c++.build.modules.builder") + set_sourcekinds("cxx") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + + before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) + if not target:get("cxx.has_modules") then + return + end + + local build_modules if target:has_tool("cxx", "clang", "clangxx") then - import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + build_modules = import("build_modules.clang") elseif target:has_tool("cxx", "gcc", "gxx") then - import("build_modules.gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + build_modules = import("build_modules.gcc") elseif target:has_tool("cxx", "cl") then - import("build_modules.msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + build_modules = import("build_modules.msvc") else local _, toolname = target:tool("cxx") raise("compiler(%s): does not support c++ module!", toolname) end - end, {batch = true}) + local common = import("build_modules.common") + + local batch = sourcebatch + + batch.objectfiles = {} + batch.dependfiles = {} + common.patch_sourcebatch(target, batch, opt) + + local modules = target:data("cxx.modules") + + local headerunits + for _, objectfile in ipairs(batch.objectfiles) do + for obj, m in pairs(modules) do + if obj == objectfile then + for name, r in pairs(m.requires) do + if r.method ~= "by-name" then + headerunits = headerunits or {} + + local type = r.method == "include-angle" and ":angle" or ":quote" + table.append(headerunits, { name = name, path = r.path, type = type, stl = common.is_stl_header(name) }) + end + end + break + end + end + end + + local headerunits_flags + local private_headerunits_flags + if headerunits then + headerunits_flags, private_headerunits_flags = build_modules.generate_headerunits(target, batchcmds, headerunits, opt) + end + + if headerunits_flags then + target:add("cxxflags", headerunits_flags, {force = true, expand = false}) + end + if private_headerunits_flags then + target:add("cxxflags", private_headerunits_flags, {force = true, expand = false}) + end + + local modules = target:data("cxx.modules") + + -- topological sort + local objectfiles = common.sort_modules_by_dependencies(batch.objectfiles, modules) + + build_modules.build_modules(target, batchcmds, objectfiles, modules, opt) + end) \ No newline at end of file diff --git a/xmake/rules/qt/qmltyperegistrar/xmake.lua b/xmake/rules/qt/qmltyperegistrar/xmake.lua index ae913c9aa..46c6b21da 100644 --- a/xmake/rules/qt/qmltyperegistrar/xmake.lua +++ b/xmake/rules/qt/qmltyperegistrar/xmake.lua @@ -101,7 +101,7 @@ rule("qt.qmltyperegistrar") } -- gen sourcefile - batchcmds:show_progress(opt.progress, "${color.build.object}generate.qt.qmltyperegistrar %s", path.filename(sourcefile)) + batchcmds:show_progress(opt.progress, "${color.build.object}generating.qt.qmltyperegistrar %s", path.filename(sourcefile)) qmltype_source = os.vrunv(qmltyperegistrar, table.join(args, metatypefiles)) -- add objectfile @@ -109,7 +109,7 @@ rule("qt.qmltyperegistrar") table.insert(target:objectfiles(), objectfile) -- compile sourcefile - batchcmds:show_progress(opt.progress, "${color.build.object}compile.qt.qmltyperegistrar %s", path.filename(sourcefile)) + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.qt.qmltyperegistrar %s", path.filename(sourcefile)) batchcmds:compile(sourcefile, objectfile) batchcmds:add_depfiles(sourcefile) -- cgit v1.3.1 From 8d8127bdc674d5267e3a2ef87b8371c9b42526d8 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 31 Jul 2022 15:29:13 +0200 Subject: Update unit tests to new add_modulefiles --- tests/projects/c++/modules/class/xmake.lua | 3 ++- tests/projects/c++/modules/dependence/xmake.lua | 3 ++- tests/projects/c++/modules/dependence2/xmake.lua | 3 ++- tests/projects/c++/modules/hello with spaces/xmake.lua | 3 ++- tests/projects/c++/modules/hello/xmake.lua | 3 ++- tests/projects/c++/modules/impl_unit/xmake.lua | 3 ++- tests/projects/c++/modules/inline_and_template/xmake.lua | 3 ++- tests/projects/c++/modules/partitions/xmake.lua | 3 ++- tests/projects/c++/modules/staticlib/xmake.lua | 2 +- tests/projects/c++/modules/submodules/xmake.lua | 3 ++- tests/projects/c++/modules/submodules2/xmake.lua | 3 ++- 11 files changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/projects/c++/modules/class/xmake.lua b/tests/projects/c++/modules/class/xmake.lua index 6d6eaddee..850f7ae18 100644 --- a/tests/projects/c++/modules/class/xmake.lua +++ b/tests/projects/c++/modules/class/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("class") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/dependence/xmake.lua b/tests/projects/c++/modules/dependence/xmake.lua index 6d64b49b1..0346e1161 100644 --- a/tests/projects/c++/modules/dependence/xmake.lua +++ b/tests/projects/c++/modules/dependence/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("dependence") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/dependence2/xmake.lua b/tests/projects/c++/modules/dependence2/xmake.lua index 6d64b49b1..0346e1161 100644 --- a/tests/projects/c++/modules/dependence2/xmake.lua +++ b/tests/projects/c++/modules/dependence2/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("dependence") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/hello with spaces/xmake.lua b/tests/projects/c++/modules/hello with spaces/xmake.lua index 4f46b699d..60188ed8a 100644 --- a/tests/projects/c++/modules/hello with spaces/xmake.lua +++ b/tests/projects/c++/modules/hello with spaces/xmake.lua @@ -2,4 +2,5 @@ add_rules("mode.release", "mode.debug") set_languages("c++20") target("A hello") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/hello/xmake.lua b/tests/projects/c++/modules/hello/xmake.lua index 2315cf287..caa462cd1 100644 --- a/tests/projects/c++/modules/hello/xmake.lua +++ b/tests/projects/c++/modules/hello/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("hello") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/impl_unit/xmake.lua b/tests/projects/c++/modules/impl_unit/xmake.lua index abe41d20a..135cf2f73 100644 --- a/tests/projects/c++/modules/impl_unit/xmake.lua +++ b/tests/projects/c++/modules/impl_unit/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("impl_unit") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/inline_and_template/xmake.lua b/tests/projects/c++/modules/inline_and_template/xmake.lua index 4810edb85..233117b26 100644 --- a/tests/projects/c++/modules/inline_and_template/xmake.lua +++ b/tests/projects/c++/modules/inline_and_template/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("inline_and_template") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/partitions/xmake.lua b/tests/projects/c++/modules/partitions/xmake.lua index 672034947..e77b8d86d 100644 --- a/tests/projects/c++/modules/partitions/xmake.lua +++ b/tests/projects/c++/modules/partitions/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("math") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua index 93045c18f..bf1d8f02f 100644 --- a/tests/projects/c++/modules/staticlib/xmake.lua +++ b/tests/projects/c++/modules/staticlib/xmake.lua @@ -2,7 +2,7 @@ set_languages("c++20") target("mod") set_kind("static") - add_files("src/mod.mpp", "src/mod.cpp") + add_modulefiles("src/mod.mpp", "src/mod.cpp") target("test") set_kind("binary") diff --git a/tests/projects/c++/modules/submodules/xmake.lua b/tests/projects/c++/modules/submodules/xmake.lua index 672034947..e77b8d86d 100644 --- a/tests/projects/c++/modules/submodules/xmake.lua +++ b/tests/projects/c++/modules/submodules/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("math") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") diff --git a/tests/projects/c++/modules/submodules2/xmake.lua b/tests/projects/c++/modules/submodules2/xmake.lua index 672034947..e77b8d86d 100644 --- a/tests/projects/c++/modules/submodules2/xmake.lua +++ b/tests/projects/c++/modules/submodules2/xmake.lua @@ -1,4 +1,5 @@ set_languages("c++20") target("math") set_kind("binary") - add_files("src/*.cpp", "src/*.mpp") + add_modulefiles("src/*.mpp") + add_files("src/*.cpp") -- cgit v1.3.1 From dee01ba2ff847c67d1da4b63565f6afe332a857c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 31 Jul 2022 15:29:13 +0200 Subject: Revert "Update unit tests to new add_modulefiles" This reverts commit 8d8127bdc674d5267e3a2ef87b8371c9b42526d8. --- tests/projects/c++/modules/class/xmake.lua | 3 +-- tests/projects/c++/modules/dependence/xmake.lua | 3 +-- tests/projects/c++/modules/dependence2/xmake.lua | 3 +-- tests/projects/c++/modules/hello with spaces/xmake.lua | 3 +-- tests/projects/c++/modules/hello/xmake.lua | 3 +-- tests/projects/c++/modules/impl_unit/xmake.lua | 3 +-- tests/projects/c++/modules/inline_and_template/xmake.lua | 3 +-- tests/projects/c++/modules/partitions/xmake.lua | 3 +-- tests/projects/c++/modules/staticlib/xmake.lua | 2 +- tests/projects/c++/modules/submodules/xmake.lua | 3 +-- tests/projects/c++/modules/submodules2/xmake.lua | 3 +-- 11 files changed, 11 insertions(+), 21 deletions(-) diff --git a/tests/projects/c++/modules/class/xmake.lua b/tests/projects/c++/modules/class/xmake.lua index 850f7ae18..6d6eaddee 100644 --- a/tests/projects/c++/modules/class/xmake.lua +++ b/tests/projects/c++/modules/class/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("class") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/dependence/xmake.lua b/tests/projects/c++/modules/dependence/xmake.lua index 0346e1161..6d64b49b1 100644 --- a/tests/projects/c++/modules/dependence/xmake.lua +++ b/tests/projects/c++/modules/dependence/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("dependence") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/dependence2/xmake.lua b/tests/projects/c++/modules/dependence2/xmake.lua index 0346e1161..6d64b49b1 100644 --- a/tests/projects/c++/modules/dependence2/xmake.lua +++ b/tests/projects/c++/modules/dependence2/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("dependence") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/hello with spaces/xmake.lua b/tests/projects/c++/modules/hello with spaces/xmake.lua index 60188ed8a..4f46b699d 100644 --- a/tests/projects/c++/modules/hello with spaces/xmake.lua +++ b/tests/projects/c++/modules/hello with spaces/xmake.lua @@ -2,5 +2,4 @@ add_rules("mode.release", "mode.debug") set_languages("c++20") target("A hello") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/hello/xmake.lua b/tests/projects/c++/modules/hello/xmake.lua index caa462cd1..2315cf287 100644 --- a/tests/projects/c++/modules/hello/xmake.lua +++ b/tests/projects/c++/modules/hello/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("hello") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/impl_unit/xmake.lua b/tests/projects/c++/modules/impl_unit/xmake.lua index 135cf2f73..abe41d20a 100644 --- a/tests/projects/c++/modules/impl_unit/xmake.lua +++ b/tests/projects/c++/modules/impl_unit/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("impl_unit") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/inline_and_template/xmake.lua b/tests/projects/c++/modules/inline_and_template/xmake.lua index 233117b26..4810edb85 100644 --- a/tests/projects/c++/modules/inline_and_template/xmake.lua +++ b/tests/projects/c++/modules/inline_and_template/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("inline_and_template") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/partitions/xmake.lua b/tests/projects/c++/modules/partitions/xmake.lua index e77b8d86d..672034947 100644 --- a/tests/projects/c++/modules/partitions/xmake.lua +++ b/tests/projects/c++/modules/partitions/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("math") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua index bf1d8f02f..93045c18f 100644 --- a/tests/projects/c++/modules/staticlib/xmake.lua +++ b/tests/projects/c++/modules/staticlib/xmake.lua @@ -2,7 +2,7 @@ set_languages("c++20") target("mod") set_kind("static") - add_modulefiles("src/mod.mpp", "src/mod.cpp") + add_files("src/mod.mpp", "src/mod.cpp") target("test") set_kind("binary") diff --git a/tests/projects/c++/modules/submodules/xmake.lua b/tests/projects/c++/modules/submodules/xmake.lua index e77b8d86d..672034947 100644 --- a/tests/projects/c++/modules/submodules/xmake.lua +++ b/tests/projects/c++/modules/submodules/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("math") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/submodules2/xmake.lua b/tests/projects/c++/modules/submodules2/xmake.lua index e77b8d86d..672034947 100644 --- a/tests/projects/c++/modules/submodules2/xmake.lua +++ b/tests/projects/c++/modules/submodules2/xmake.lua @@ -1,5 +1,4 @@ set_languages("c++20") target("math") set_kind("binary") - add_modulefiles("src/*.mpp") - add_files("src/*.cpp") + add_files("src/*.cpp", "src/*.mpp") -- cgit v1.3.1 From 37af4ce4b13e5b7638fae804f967e28459626958 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 2 Aug 2022 18:20:20 +0200 Subject: [C++20 Modules] Remove add/remove_modulefiles --- xmake/core/project/target.lua | 106 ---------------------------------------- xmake/languages/c++/load.lua | 1 - xmake/languages/objc++/load.lua | 1 - 3 files changed, 108 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 26223258c..b00cbe15a 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1566,110 +1566,6 @@ function _instance:headerfiles(outputdir, opt) return srcheaders, dstheaders end --- get the module files -function _instance:modulefiles(outputdir) - local modules = self:get("modulefiles") - - -- get the installed module directory - local moduledir = outputdir - if not moduledir and self:installdir() then - path.join(self:installdir(), "include") - end - - -- get the extra information - local extrainfo = table.wrap(self:get("__extra_modulefiles")) - - -- get the source paths and destinate paths - local srcmodules = {} - local dstmodules = {} - local srcmodules_removed = {} - local removed_count = 0 - for _, module in ipairs(table.wrap(modules)) do - -- mark as removed files? - local removed = false - local prefix = "__remove_" - if module:startswith(prefix) then - module = module:sub(#prefix + 1) - removed = true - end - - -- get the root directory - local rootdir, count = module:gsub("|.*$", ""):gsub("%(.*%)$", "") - if count == 0 then - rootdir = nil - end - if rootdir and rootdir:trim() == "" then - rootdir = "." - end - - -- remove '(' and ')' first - local srcpaths = module:gsub("[%(%)]", "") - if srcpaths then - - -- get the source paths - srcpaths = os.match(srcpaths) - if srcpaths then - if removed then - removed_count = removed_count + #srcpaths - table.join2(srcmodules_removed, srcpaths) - else - -- add the source modules - table.join2(srcmodules, srcpaths) - - -- get the destinate directories if the install directory exists - if moduledir then - local prefixdir = (extrainfo[module] or {}).prefixdir - for _, srcpath in ipairs(srcpaths) do - local dstdir = moduledir - if prefixdir then - dstdir = path.join(dstdir, prefixdir) - end - local dstmodule = nil - if rootdir then - dstmodule = path.absolute(path.relative(srcpath, rootdir), dstdir) - else - dstmodule = path.join(dstdir, path.filename(srcpath)) - end - table.insert(dstmodules, dstmodule) - end - end - end - end - end - end - - -- remove all module files which need be removed - if removed_count > 0 then - table.remove_if(srcmodules, function (i, srcmodule) - for _, removed_file in ipairs(srcmodules_removed) do - local pattern = path.translate(removed_file:gsub("|.*$", "")) - if pattern:sub(1, 2):find('%.[/\\]') then - pattern = pattern:sub(3) - end - pattern = path.pattern(pattern) - if srcmodule:match(pattern) then - if i <= #dstmodules then - table.remove(dstmodules, i) - end - return true - end - end - end) - end - - return srcmodules, dstmodules -end - --- get the bmi files -function _instance:bmifiles(outputdir) - local compilerinst = self:compiler() - - -- get the installed bmi directory - local bmidir = bmi_outputdir or path.join(self:installdir(), "lib", compilerinst:name() + "-" + compilerinst:version()) - - return self:_copiedfiles("bmifiles", bmidir) -end - -- get the configuration files function _instance:configfiles(outputdir) return self:_copiedfiles("configfiles", outputdir or self:configdir(), function (dstpath, fileinfo) @@ -2249,7 +2145,6 @@ function target.apis() , "target.set_rundir" -- target.add_xxx , "target.add_files" - , "target.add_modulefiles" , "target.add_cleanfiles" , "target.add_configfiles" , "target.add_installfiles" @@ -2258,7 +2153,6 @@ function target.apis() -- target.remove_xxx , "target.remove_files" , "target.remove_headerfiles" - , "target.remove_modulefiles" } , dictionary = { diff --git a/xmake/languages/c++/load.lua b/xmake/languages/c++/load.lua index b3c2b2ae3..16380ab3c 100644 --- a/xmake/languages/c++/load.lua +++ b/xmake/languages/c++/load.lua @@ -224,7 +224,6 @@ function _get_apis() -- target.add_xxx , "target.add_headers" -- TODO deprecated , "target.add_headerfiles" - , "target.add_modulefiles" , "target.add_linkdirs" , "target.add_includedirs" , "target.add_sysincludedirs" diff --git a/xmake/languages/objc++/load.lua b/xmake/languages/objc++/load.lua index 2950a28f6..85df22850 100644 --- a/xmake/languages/objc++/load.lua +++ b/xmake/languages/objc++/load.lua @@ -80,7 +80,6 @@ function _get_apis() -- target.add_xxx , "target.add_headers" -- TODO deprecated , "target.add_headerfiles" - , "target.add_modulefiles" , "target.add_linkdirs" , "target.add_includedirs" , "target.add_sysincludedirs" -- cgit v1.3.1 From ab70577eccc2f4b003041e5c8850a775ddc81be0 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 2 Aug 2022 18:32:58 +0200 Subject: [C++20 Modules] Improve code --- xmake/rules/c++/modules/xmake.lua | 52 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 0f03b9b13..8992e3133 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -20,15 +20,18 @@ -- define rule: c++.build.modules rule("c++.build.modules") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + add_deps("c++.build.modules.dependencies") add_deps("c++.build.modules.builder") + add_deps("c++.build.modules.install") on_config(function (target) - local target_with_modules = (target:modulefiles() and #target:modulefiles() > 0) and true or false + local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false for _, dep in ipairs(target:orderdeps()) do local modulefiles = dep:get("modulefiles") if modulefiles and #modulefiles > 0 then - target_with_modules = true + target_with_modules = target:sourcebatches()["c++.build.modules"] and true or target_with_modules break end end @@ -55,14 +58,15 @@ rule("c++.build.modules") -- load parent build_modules.load_parent(target, opt) - for _, modulefile in ipairs(target:modulefiles()) do - target:add("files", modulefile) - end - target:set("cxx.has_modules", true) end end) + +rule("c++.build.modules.dependencies") + set_sourcekinds("cxx") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + before_build(function(target, opt) if not target:get("cxx.has_modules") then return @@ -80,33 +84,20 @@ rule("c++.build.modules") raise("compiler(%s): does not support c++ module!", toolname) end - -- build dependency data local common = import("build_modules.common") - local moduleinfos = {} - for _, sourcebatch in pairs(target:sourcebatches()) do - local batch = sourcebatch - - if batch.rulename == "c++.build.modules.builder" then - batch.objectfiles = {} - batch.dependfiles = {} - common.patch_sourcebatch(target, batch, opt) - end - - if batch.rulename:startswith("c++.build") then - build_modules.generate_dependencies(target, batch, opt) - local infos = common.load(target, batch, opt) + -- build dependency data + local batch = target:sourcebatches()["c++.build.modules.dependencies"] + common.patch_sourcebatch(target, batch, opt) - table.join2(moduleinfos, infos or {}) - end - end + build_modules.generate_dependencies(target, batch, opt) + local moduleinfos = common.load(target, batch, opt) local modules = common.parse_dependency_data(target, moduleinfos, opt) target:data_set("cxx.modules", modules) end) - rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") @@ -131,6 +122,8 @@ rule("c++.build.modules.builder") local common = import("build_modules.common") local batch = sourcebatch + print(sourcebatch) + print(batch) batch.objectfiles = {} batch.dependfiles = {} @@ -174,4 +167,13 @@ rule("c++.build.modules.builder") local objectfiles = common.sort_modules_by_dependencies(batch.objectfiles, modules) build_modules.build_modules(target, batchcmds, objectfiles, modules, opt) - end) \ No newline at end of file + end) + +rules("c++.build.modules.install") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + + on_config(function (target) + local sourcebatch = target:sourcebatches()["c++.build.modules.install"] + + target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) + end \ No newline at end of file -- cgit v1.3.1 From 92b8b6629b6c3b4b59d78835b7e4719313c04ae1 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 02:35:01 +0200 Subject: [C++20 Modules] Improve support on MSVC Clang and GCC --- xmake/rules/c++/modules/build_modules/clang.lua | 210 ---------- xmake/rules/c++/modules/build_modules/common.lua | 409 -------------------- xmake/rules/c++/modules/build_modules/gcc.lua | 232 ----------- xmake/rules/c++/modules/build_modules/msvc.lua | 249 ------------ xmake/rules/c++/modules/modules_support/clang.lua | 270 +++++++++++++ xmake/rules/c++/modules/modules_support/common.lua | 423 +++++++++++++++++++++ xmake/rules/c++/modules/modules_support/gcc.lua | 259 +++++++++++++ xmake/rules/c++/modules/modules_support/msvc.lua | 327 ++++++++++++++++ xmake/rules/c++/modules/xmake.lua | 64 ++-- 9 files changed, 1308 insertions(+), 1135 deletions(-) delete mode 100644 xmake/rules/c++/modules/build_modules/clang.lua delete mode 100644 xmake/rules/c++/modules/build_modules/common.lua delete mode 100644 xmake/rules/c++/modules/build_modules/gcc.lua delete mode 100644 xmake/rules/c++/modules/build_modules/msvc.lua create mode 100644 xmake/rules/c++/modules/modules_support/clang.lua create mode 100644 xmake/rules/c++/modules/modules_support/common.lua create mode 100644 xmake/rules/c++/modules/modules_support/gcc.lua create mode 100644 xmake/rules/c++/modules/modules_support/msvc.lua diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua deleted file mode 100644 index bce008766..000000000 --- a/xmake/rules/c++/modules/build_modules/clang.lua +++ /dev/null @@ -1,210 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file clang.lua --- - --- imports -import("core.tool.compiler") -import("core.project.project") -import("core.project.depend") -import("core.base.json") -import("core.project.config") -import("utils.progress") -import("private.action.build.object", {alias = "objectbuilder"}) - -local default_flags = { "-std=c++20" } - --- load parent target with modules files -function load_parent(target, opt) - local common = import("common") - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - - -- add module flags - target:add("cxxflags", "-fmodules") - - -- add the module cache directory - target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", {force = true}) - target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, "-fprebuilt-module-path=" .. stlcachedir, {force = true}) - - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) - dep:add("cxxflags", "-fmodules") - dep:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", {force = true}) - target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, "-fprebuilt-module-path=" .. stlcachedir, {force = true}) - target:add("cxxflags", "-fprebuilt-module-path=" .. cachedir, {force = true}) - end -end - --- check C++20 module support -function check_module_support(target) - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules") then - modulesflag = "-fmodules" - end - assert(modulesflag, "compiler(clang): does not support c++ module!") - - target:data_set("cxx.has_p1689r4", false) -end - -function generate_dependencies(target, sourcebatch, opt) - local common = import("common") - local cachedir = common.get_cache_dir(target) - - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local dependfile = target:dependfile(sourcefile) - depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) - - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) - - if target:data("cxx.has_p1689r4") then - else -- fallback as clang doesn't support p1689r4 - local dependinfo = common.fallback_generate_dependencies(target, jsonfile, sourcefile) - local jsondata = json.encode(dependinfo) - - io.writefile(jsonfile, jsondata) - end - - local dependinfo = io.readfile(jsonfile) - - return { moduleinfo = dependinfo } - end, {dependfile = dependfile, files = {sourcefile}}) - end -end - --- generate target header units -function generate_headerunits(target, batchcmds, sourcebatch, opt) - local common = import("common") - - local compinst = target:compiler("cxx") - - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - - -- build headerunits - local objectfiles = {} - local public_flags = {} - local private_flags = {} - for _, headerunit in ipairs(sourcebatch) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - - local objectfile = target:objectfile(file) - - local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local bmifilename = path.basename(objectfile) .. ".pcm" - - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - local args = { "-fmodules-cache-path=" .. cachedir, "-emit-module", "-c", "-o", bmifile } - if headerunit.type == ":quote" then - table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path }) - elseif headerunit.type == ":angle" then - table.join2(args, { "-x", "c++-system-header", headerunit.name }) - end - - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) - - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - - table.append(public_flags, "-fmodule-file=" .. bmifile) - else - local bmifile = path.join(stlcachedir, headerunit.name .. ".pcm") - - if not os.isfile(bmifile) then - local args = { "-fmodules-cache-path=" .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path } - - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) - - end - - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - - table.append(private_flags, "-fmodule-file=" .. bmifile) - end - end - - return public_flags, private_flags -end - --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) - - local compinst = target:compiler("cxx") - - -- append deps modules - local flags = {} - for _, dep in ipairs(target:orderdeps()) do - table.join2(flags, dep:data("cxx.modules.flags")) - end - flags = table.unique(flags) - target:add("cxxflags", flags, {force = true, expand = false}) - - local common_args = { "-fmodules-cache-path=" .. cachedir, "-emit-module-interface" } - for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - - if m then - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - local args = { } - local flag = {} - for name, provide in pairs(m.provides) do - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - - local bmifile = provide.bmi - table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) - - batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - - table.join2(flag, { "-fmodule-file=" .. bmifile }) - end - - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args)) - - target:add("cxxflags", flag, {public = true, force = true}) - for _, f in ipairs(flag) do - target:data_add("cxx.modules.flags", f) - end - end - end -end diff --git a/xmake/rules/c++/modules/build_modules/common.lua b/xmake/rules/c++/modules/build_modules/common.lua deleted file mode 100644 index bf64386e4..000000000 --- a/xmake/rules/c++/modules/build_modules/common.lua +++ /dev/null @@ -1,409 +0,0 @@ -import("core.base.json") -import("core.project.config") -import("core.tool.compiler") -import("core.cache.globalcache") -import("core.project.project") -import("lib.detect") -import("lib.detect.find_package") -import("lib.detect.find_file") - -local stl_headers = { - "algorithm", - "forward_list", - "numbers", - "stop_token", - "any", - "fstream", - "numeric", - "streambuf", - "array", - "functional", - "optional", - "string", - "atomic", - "future", - "ostream", - "string_view", - "barrier", - "initializer_list", - "queue", - "bit", - "iomanip", - "random", - "syncstream", - "bitset", - "ios", - "ranges", - "system_error", - "charconv", - "iosfwd", - "ratio", - "thread", - "chrono", - "iostream", - "regex", - "tuple", - "codecvt", - "istream", - "scoped_allocator", - "typeindex", - "compare", - "iterator", - "semaphore", - "typeinfo", - "complex", - "latch", - "set", - "type_traits", - "concepts", - "limits", - "shared_mutex", - "unordered_map", - "condition_variable", - "list", - "source_location", - "unordered_set", - "coroutine", - "locale", - "span", - "utility", - "deque", - "map", - "spanstream", - "valarray", - "exception", - "memory", - "sstream", - "variant", - "execution", - "memory_resource", - "stack", - "vector", - "filesystem", - "mutex", - "version", - "format", - "new", - "type_traits", - "string_view", - "stdexcept"} - -function get_stl_headers() - return stl_headers -end - -function is_stl_header(header) - for _, stl_header in ipairs(stl_headers) do - if stl_header == header then - return true - end - end - - return false -end - -function get_stlcache_dir(target) - local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") - if target:has_tool("cxx", "clang", "clangxx") then - stlcachedir = path.join(config.buildir(), "stlmodules", "cache") - end - if not os.isdir(stlcachedir) then - os.mkdir(stlcachedir) - end - - return stlcachedir -end - -function get_cache_dir(target) - local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - if not os.isdir(cachedir) then - os.mkdir(cachedir) - end - - return cachedir -end - -function patch_sourcebatch(target, sourcebatch, opt) - local cachedir = get_cache_dir(target) - - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - local dependfile = target:dependfile(objectfile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, dependfile) - end - -end - -function get_bmi_ext(target) - if target:has_tool("cxx", "gcc", "gxx") then - return ".gcm" - elseif target:has_tool("cxx", "cl") then - return ".ifc" - elseif target:has_tool("cxx", "clang", "clangxx") then - return ".pcm" - end - - assert(false) -end - -function load(target, sourcebatch, opt) - local cachedir = get_cache_dir(target) - - local moduleinfos - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local dependfile = target:dependfile(sourcefile) - if os.isfile(dependfile) then - local data = io.load(dependfile) - - if data then - moduleinfos = moduleinfos or {} - - local moduleinfo = json.decode(data.moduleinfo) - moduleinfo.sourcefile = sourcefile - if moduleinfo then - table.append(moduleinfos, moduleinfo) - end - end - end - end - - return moduleinfos -end - -function parse_dependency_data(target, moduleinfos, opt) - local cachedir = get_cache_dir(target) - - local modules - for _, moduleinfo in ipairs(moduleinfos) do - assert(moduleinfo.version <= 1) - for _, rule in ipairs(moduleinfo.rules) do - modules = modules or {} - - local m = {} - - for _, provide in ipairs(rule.provides) do - m.provides = m.provides or {} - - if provide["compiled-module-path"] then - if not path.is_absolute(provide["compiled-module-path"]) then - m.provides[provide["logical-name"] ] = path.absolute(provide["compiled-module-path"]) - else - m.provides[provide["logical-name"] ] = provide["compiled-module-path"] - end - else -- assume path with name - local name = provide["logical-name"] .. get_bmi_ext(target) - name:replace(":", "-") - - m.provides[provide["logical-name"] ] = { - bmi = path.join(cachedir, name), - sourcefile = moduleinfo.sourcefile - } - end - end - - modules[rule["primary-output"] ] = m - end - end - - for _, moduleinfo in ipairs(moduleinfos) do - for _, rule in ipairs(moduleinfo.rules) do - local m = modules[rule["primary-output"] ] - for _, r in ipairs(rule.requires) do - m.requires = m.requires or {} - - local p = r["source-path"] - if not p then - for _, dependency in pairs(modules) do - if dependency.provides and dependency.provides[r["logical-name"] ] then - p = dependency.provides[r["logical-name"] ].bmi - break - end - end - end - - m.requires[r["logical-name"] ] = { - method = r["lookup-method"] or "by-name", - path = p, - unique = r["unique-on-source-path"] or false - } - end - end - end - - return modules -end - -function _topological_sort_visit(node, nodes, modules, output) - if node.marked then - return - end - - assert(not node.tempmarked) - - node.tempmarked = true - - local m1 = modules[node.objectfile] - - assert(m1.provides) - for _, n in ipairs(nodes) do - if not n.tempmarked then - local m2 = modules[n.objectfile] - - for name, provide in pairs(m1.provides) do - if m2.requires and m2.requires[name] then - _topological_sort_visit(n, nodes, modules, output) - end - end - end - end - - node.tempmarked = false - node.marked = true - - table.insert(output, 1, node.objectfile) -end - -function _topological_sort_has_node_without_mark(nodes) - for _, node in ipairs(nodes) do - if not node.marked then - return true - end - end - - return false -end - -function _topological_sort_get_first_unmarked_node(nodes) - for _, node in ipairs(nodes) do - if not node.marked and not node.tempmarked then - return node - end - end -end - -function sort_modules_by_dependencies(objectfiles, modules) - local output = {} - - local nodes = {} - for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - - if m.provides then - table.append(nodes, { marked = false, tempmarked = false, objectfile = objectfile }) - end - end - - while _topological_sort_has_node_without_mark(nodes) do - local node = _topological_sort_get_first_unmarked_node(nodes) - - _topological_sort_visit(node, nodes, modules, output) - end - - return output -end - -function find_quote_header_file(target, sourcefile, file) - local p = path.join(path.directory(path.absolute(sourcefile, project.directory())), file) - - assert(os.isfile(p)) - - return p -end - -function find_angle_header_file(target, file) - -- check if the header is in subtarget - - local headerpaths = {} - - for _, dep in ipairs(target:orderdeps()) do - table.append(headerpaths, dep:scriptdir()) - end - - if project.required_packages then - for _, name in ipairs(target:get("packages")) do - local package = project.required_package(name) - table.join2(headerpaths, package:get("sysincludedirs")) - end - end - - table.join2(headerpaths, target:get("includedirs")) - - local p = find_file(file, table.join(headerpaths, { "/usr/include/**", "/usr/local/include/**" })) - - assert(os.isfile(p)) - - return p -end - -function fallback_generate_dependencies(target, jsonfile, sourcefile) - local output = { - version = 0, - revision = 0, - rules = {} - } - - local rule = { - outputs = { - jsonfile - } - } - rule["primary-output"] = target:objectfile(sourcefile) - - local module_name - local module_deps = {} - local sourcecode = io.readfile(sourcefile) - sourcecode = sourcecode:gsub("//.-\n", "\n") - sourcecode = sourcecode:gsub("/%*.-%*/", "") - for _, line in ipairs(sourcecode:split("\n", {plain = true})) do - if not module_name then - module_name = line:match("export%s+module%s+(.+)%s*;") - end - - local module_depname = line:match("import%s+(.+)%s*;") - - if module_depname then - local module_dep = {} - - -- partition? import :xxx; - if module_depname:startswith(":") then - module_depname = module_name .. module_depname - elseif module_depname:startswith("\"") then - module_depname = module_depname:sub(2, -2) - module_dep["lookup-method"] = "include-quote" - module_dep["unique-on-source-path"] = true - module_dep["source-path"] = find_quote_header_file(target, sourcefile, module_depname) - elseif module_depname:startswith("<") then - module_depname = module_depname:sub(2, -2) - module_dep["lookup-method"] = "include-angle" - module_dep["unique-on-source-path"] = true - module_dep["source-path"] = find_angle_header_file(target, module_depname) - end - - module_dep["logical-name"] = module_depname - - table.insert(module_deps, module_dep) - end - end - - if module_name then - table.append(rule.outputs, module_name .. get_bmi_ext(target)) - - local provide = {} - provide["logical-name"] = module_name - provide["source-path"] = path.absolute(sourcefile, project.directory()) - - rule.provides = {} - table.append(rule.provides, provide) - end - - rule.requires = module_deps - - table.append(output.rules, rule) - - return output -end \ No newline at end of file diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua deleted file mode 100644 index 97bb9cc9a..000000000 --- a/xmake/rules/c++/modules/build_modules/gcc.lua +++ /dev/null @@ -1,232 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file gcc.lua --- - --- imports -import("core.tool.compiler") -import("core.project.project") -import("core.project.depend") -import("core.base.json") -import("core.project.config") -import("utils.progress") -import("private.action.build.object", {alias = "objectbuilder"}) - -local default_flags = {"-std=c++20"} - -function get_module_mapper() - local mapper_file = path.join(config.buildir(), "mapper.txt") - if not os.isfile(mapper_file) then - io.writefile(mapper_file, "") - end - - return mapper_file -end - -function add_module_to_mapper(file, module, bmi) - for line in io.lines(file) do - if line:startswith(module .. " ") then - return false - end - end - - local f = io.open(file, "a") - f:printf("%s %s\n", module, bmi) - f:close() - - return true -end - --- load parent target with modules files -function load_parent(target, opt) - local common = import("common") - local cachedir = common.get_cache_dir(target) - - target:add("cxxflags", "-fmodules-ts") - if os.isfile(get_module_mapper()) then - os.rm(get_module_mapper()) - end - target:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) - - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) - dep:add("cxxflags", "-fmodules-ts") - dep:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) - end -end - --- check C++20 module support -function check_module_support(target) - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(gcc): does not support c++ module!") - - if compinst:has_flags("-fdep-format=trtbd") then - target:data_set("cxx.has_p1689r4", true) - end -end - -function generate_dependencies(target, sourcebatch, opt) - local common = import("common") - local cachedir = common.get_cache_dir(target) - local compinst = target:compiler("cxx") - local common_args = {"-E", "-x", "c++"} - - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local dependfile = target:dependfile(sourcefile) - depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) - - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) - - if target:data("cxx.has_p1689r4") then - local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) - local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) - - local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, "-fdep-file=" .. jsonfile, "-fdep-format=trtbd", "-fdep-output=" .. target:objectfile(sourcefile), "-o", ifile} - - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) - else -- fallback as GCC doesn't fully support p1689r4 - local dependinfo = common.fallback_generate_dependencies(target, jsonfile, sourcefile) - local jsondata = json.encode(dependinfo) - - io.writefile(jsonfile, jsondata) - end - - local dependinfo = io.readfile(jsonfile) - - return { moduleinfo = dependinfo } - end, {dependfile = dependfile, files = {sourcefile}}) - end -end - --- generate target header units -function generate_headerunits(target, batchcmds, sourcebatch, opt) - local common = import("common") - - local compinst = target:compiler("cxx") - - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - - local mapper_file = get_module_mapper() - - -- build headerunits - local objectfiles = {} - for _, headerunit in ipairs(sourcebatch) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - - local objectfile = target:objectfile(file) - - local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local bmifilename = path.basename(objectfile) .. ".gcm" - - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then - local args = { "-c" } - if headerunit.type == ":quote" then - table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) - add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) - elseif headerunit.type == ":angle" then - table.join2(args, { "-x", "c++-system-header", headerunit.name }) - add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) - end - - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) - - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - end - else - local bmifile = path.join(stlcachedir, headerunit.name .. ".gcm") - - if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then - if not os.isfile(bmifile) then - local args = { "-c", "-x", "c++-system-header", headerunit.name } - - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args)) - - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - end - end - end - - end -end - --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) - - local compinst = target:compiler("cxx") - - local mapper_file = get_module_mapper() - local common_args = { "-x", "c++" } - for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - - if m then - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - local args = { "-o", objectfile } - for name, provide in pairs(m.provides) do - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - - local bmifile = provide.bmi - if add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then - table.join2(args, { "-c", provide.sourcefile }) - - batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - end - end - - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args)) - - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) - - target:add("objectfiles", objectfile) - end - end -end - diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua deleted file mode 100644 index ac1386a27..000000000 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ /dev/null @@ -1,249 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file msvc.lua --- - --- imports -import("core.tool.compiler") -import("core.project.depend") -import("utils.progress") -import("private.action.build.object", {alias = "objectbuilder"}) - -local default_flags = {"/EHsc", "/nologo", "/std:c++20", "/experimental:module"} - --- load parent target with modules files -function load_parent(target, opt) - local common = import("common") - -- get modules flag - local compinst = target:compiler("cxx") - - -- add module flags - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - - target:add("cxxflags", "/experimental:module") - target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) - target:add("cxxflags", {"/ifcSearchDir", stlcachedir}, {force = true, expand = false}) - - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) - dep:add("cxxflags", "/experimental:module") - target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false}) - end - - for _, toolchain_inst in ipairs(target:toolchains()) do - if toolchain_inst:name() == "msvc" then - local vcvars = toolchain_inst:config("vcvars") - if vcvars.VCInstallDir and vcvars.VCToolsVersion then - local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") - if os.isdir(stdifcdir) then - target:add("cxxflags", {"/stdIfcDir", winos.short_path(stdifcdir)}, {force = true, expand = false}) - end - end - break - end - end -end - --- check C++20 module support -function check_module_support(target) - local compinst = target:compiler("cxx") - - if compinst:has_flags("/experimental:module", "cxxflags") then - modulesflag = "/experimental:module" - end - assert(modulesflag, "compiler(msvc): does not support c++ module!") - - -- get output flag - local outputflag - if compinst:has_flags("/ifcOutput", "cxxflags") then - outputflag = "/ifcOutput" - end - assert(outputflag, "compiler(msvc): does not support c++ module!") - - -- get interface flag - local interfaceflag - if compinst:has_flags("/interface", "cxxflags") then - interfaceflag = "/interface" - end - assert(interfaceflag, "compiler(msvc): does not support c++ module!") - - -- get reference flag - local referenceflag - if compinst:has_flags("/reference", "cxxflags") then - referenceflag = "/reference" - end - assert(referenceflag, "compiler(msvc): does not support c++ module!") - - -- get stdifcdir flag - local stdifcdirflag - if compinst:has_flags("/stdIfcDir", "cxxflags") then - stdifcdirflag = "/stdIfcDir" - end - assert(stdifcdirflag, "compiler(msvc): does not support c++ module!") -end - - --- generate dependency files -function generate_dependencies(target, sourcebatch, opt) - local compinst = target:compiler("cxx") - local toolchain = target:toolchain("msvc") - local vcvars = toolchain:config("vcvars") - - local common = import("common") - local cachedir = common.get_cache_dir(target) - local common_args = {"/TP", "/scanDependencies"} - - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local dependfile = target:dependfile(sourcefile) - 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()))) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local jsonfile = path.join(outdir, path.filename(sourcefile) .. ".json") - local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} - - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) - - local dependinfo = io.readfile(jsonfile) - - return { moduleinfo = dependinfo } - end, {dependfile = dependfile, files = {sourcefile}}) - end -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") - - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - - -- build headerunits - local common_args = {"/TP", "/exportHeader", "/c"} - local objectfiles = {} - local public_flags = {} - local private_flags = {} - for _, headerunit in ipairs(sourcebatch) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - - local objectfile = target:objectfile(file) - - local outdir = path.join(cachedir, "include", path.directory(headerunit.name)) - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local bmifilename = path.basename(objectfile) .. ".ifc" - - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - local args = {"/headerName" .. headerunit.type, headerunit.path, "/ifcOutput", outdir, "/Fo" .. objectfile} - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args), {envs = vcvars}) - - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) - - local flag = {"/headerUnit" .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} - table.join2(public_flags, flag) - target:add("objectfiles", objectfile) - else - local bmifile = path.join(stlcachedir, headerunit.name .. ".ifc") - local args = {"/exportHeader", "/headerName:angle", headerunit.name, "/ifcOutput", stlcachedir} - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, args), {envs = vcvars}) - - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - - local flag = {"/headerUnit:angle", headerunit.name .. "=" .. headerunit.name .. ".ifc"} - table.join2(private_flags, flag) - end - end - - return public_flags, private_flags -end - --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) - - local compinst = target:compiler("cxx") - local toolchain = target:toolchain("msvc") - local vcvars = toolchain:config("vcvars") - - -- 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 = {"/TP"} - for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - - if m then - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end - - local args = {"/c", "/Fo" .. objectfile} - - local flag = {} - for name, provide in pairs(m.provides) do - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - - local bmifile = provide.bmi - table.join2(args, {"/interface", "/ifcOutput", bmifile, provide.sourcefile}) - - batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - - flag = {"/reference", name .. "=" .. path.filename(bmifile)} - end - - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}) or default_flags, common_args, args, bmi_args), {envs = vcvars}) - - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) - - target:add("cxxflags", flag, {force = true, expand = false}) - for _, f in ipairs(flag) do - target:data_add("cxx.modules.flags", f) - end - target:add("objectfiles", objectfile) - end - end -end diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua new file mode 100644 index 000000000..e12c7afed --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -0,0 +1,270 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file clang.lua +-- + +-- imports +import("core.tool.compiler") +import("core.project.project") +import("core.project.depend") +import("core.project.config") +import("utils.progress") +import("private.action.build.object", {alias = "objectbuilder"}) + +modulesflag = nil +modulestsflag = nil +implicitmodules = nil +implicitmodulemapsflag = nil +prebuiltmodulepathflag = nil + +function get_bmi_ext() + return ".pcm" +end + +-- load parent target with modules files +function load_parent(target, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + -- add module flags + target:add("cxxflags", modulesflag or modulestsflag) + + -- add the module cache directory + target:add("cxxflags", implicitmodulesflag, {force = true}) + target:add("cxxflags", implicitmodulemapsflag, {force = true}) + + target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.get_cache_dir(dep) + target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) + end +end + +-- check C++20 module support +function check_module_support(target) + local compinst = compiler.load("cxx", {target = target}) + + if compinst:has_flags("-fmodules", "cxxflags", {flagskey = "clang_modules"}) then + modulesflag = "-fmodules" + end + + if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "clang_modules_ts"}) then + modulestsflag = "-fmodules-ts" + end + assert(modulesflag or modulestsflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -fimplicit-modules", "cxxflags", {flagskey = "clang_implicit_modules"}) then + implicitmodulesflag = "-fimplicit-modules" + end + assert(implicitmodulesflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -fimplicit-module-maps" .. os.tmpdir(), "cxxflags", {flagskey = "clang_implicit_module_path"}) then + implicitmodulemapsflag = "-fimplicit-module-maps" + end + assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -fprebuilt-module-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_prebuild_module_path"}) then + prebuiltmodulepathflag = "-fprebuilt-module-path=" + end + assert(prebuiltmodulepathflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -fmodules-cache-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_modules_cache_path"}) then + modulecachepathflag = "-fmodules-cache-path=" + end + assert(modulecachepathflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -emit-module", "cxxflags", {flagskey = "clang_emit_module"}) then + emitmoduleflag = " -emit-module" + end + assert(emitmoduleflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -fmodule-file=" .. os.tmpfile() .. get_bmi_ext(), "cxxflags", {flagskey = "clang_module_file"}) then + modulefileflag = "-fmodule-file=" + end + assert(modulefileflag, "compiler(clang): does not support c++ module!") + + if compinst:has_flags((modulesflag or modulestsflag) .. " -emit-module-interface", "cxxflags", {flagskey = "clang_emit_module_interface"}) then + emitmoduleinterfaceflag = "-emit-module-interface" + end + assert(emitmoduleinterfaceflag, "compiler(clang): does not support c++ module!") +end + +function toolchain_include_directories(target) + if is_plat("linux") then + return { "/usr/include/**", "/usr/local/include/**" } + end + + return {} +end + +function generate_dependencies(target, sourcebatch, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function() + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + + -- no support of p1689 atm + common.fallback_generate_dependencies(target, jsonfile, sourcefile) + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) + end +end + +-- generate target header units +function generate_headerunits(target, batchcmds, sourcebatch, opt) + local common = import("common") + + local compinst = target:compiler("cxx") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + -- build headerunits + local objectfiles = {} + local public_flags = {} + local private_flags = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir + if headerunit.type == ":quote" then + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + else + outdir = path.join(cachedir, path.directory(headerunit.path)) + end + + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. get_bmi_ext() + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile } + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path }) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + end + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.append(public_flags, modulefileflag .. bmifile) + else + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + + if not os.isfile(bmifile) then + local args = { modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path } + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + end + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.append(private_flags, modulefileflag .. bmifile) + end + end + + return public_flags, private_flags +end + +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") + + -- append deps modules + local flags = {} + for _, dep in ipairs(target:orderdeps()) do + table.join2(flags, dep:data("cxx.modules.flags")) + end + flags = table.unique(flags) + target:add("cxxflags", flags, {force = true, expand = false}) + + local common_args = { modulecachepathflag .. cachedir } + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = { emitmoduleinterfaceflag } + local flag = {} + local bmifiles = {} + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) + table.join2(bmifiles, bmifile) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.join2(flag, { modulefileflag .. bmifile }) + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles, {"-c", "-o", objectfile})) + + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + target:add("cxxflags", flag, {public = true, force = true}) + target:add("objectfiles", objectfile) + for _, f in ipairs(flag) do + target:data_add("cxx.modules.flags", f) + end + end + end +end diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua new file mode 100644 index 000000000..0bfcc7211 --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -0,0 +1,423 @@ +import("core.base.json") +import("core.project.config") +import("core.tool.compiler") +import("core.project.project") +import("lib.detect.find_file") + +local stl_headers = { + "algorithm", + "forward_list", + "numbers", + "stop_token", + "any", + "fstream", + "numeric", + "streambuf", + "array", + "functional", + "optional", + "string", + "atomic", + "future", + "ostream", + "string_view", + "barrier", + "initializer_list", + "queue", + "bit", + "iomanip", + "random", + "syncstream", + "bitset", + "ios", + "ranges", + "system_error", + "charconv", + "iosfwd", + "ratio", + "thread", + "chrono", + "iostream", + "regex", + "tuple", + "codecvt", + "istream", + "scoped_allocator", + "typeindex", + "compare", + "iterator", + "semaphore", + "typeinfo", + "complex", + "latch", + "set", + "type_traits", + "concepts", + "limits", + "shared_mutex", + "unordered_map", + "condition_variable", + "list", + "source_location", + "unordered_set", + "coroutine", + "locale", + "span", + "utility", + "deque", + "map", + "spanstream", + "valarray", + "exception", + "memory", + "sstream", + "variant", + "execution", + "memory_resource", + "stack", + "vector", + "filesystem", + "mutex", + "version", + "format", + "new", + "type_traits", + "string_view", + "stdexcept"} + +function get_stl_headers() + return stl_headers +end + +function is_stl_header(header) + for _, stl_header in ipairs(stl_headers) do + if stl_header == header then + return true + end + end + + return false +end + +function get_stlcache_dir(target) + local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") + if target:has_tool("cxx", "clang", "clangxx") then + stlcachedir = path.join(config.buildir(), "stlmodules", "cache") + end + if not os.isdir(stlcachedir) then + os.mkdir(stlcachedir) + end + + return path.translate(stlcachedir) +end + +function get_cache_dir(target) + local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + if not os.isdir(cachedir) then + os.mkdir(cachedir) + end + + return path.translate(cachedir) +end + +function patch_sourcebatch(target, sourcebatch, opt) + local cachedir = get_cache_dir(target) + + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + local dependfile = target:dependfile(objectfile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, dependfile) + end + +end + +function get_bmi_ext(target) + if target:has_tool("cxx", "gcc", "gxx") then + return import("gcc").get_bmi_ext() + elseif target:has_tool("cxx", "cl") then + return import("msvc").get_bmi_ext() + elseif target:has_tool("cxx", "clang", "clangxx") then + return import("clang").get_bmi_ext() + end + + assert(false) +end + +function load(target, sourcebatch, opt) + local cachedir = get_cache_dir(target) + + local moduleinfos + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + if os.isfile(dependfile) then + local data = io.load(dependfile) + + if data then + moduleinfos = moduleinfos or {} + + local moduleinfo = json.decode(data.moduleinfo) + moduleinfo.sourcefile = sourcefile + if moduleinfo then + table.append(moduleinfos, moduleinfo) + end + end + end + end + + return moduleinfos +end + +function parse_dependency_data(target, moduleinfos, opt) + local cachedir = get_cache_dir(target) + + local modules + for _, moduleinfo in ipairs(moduleinfos) do + assert(moduleinfo.version <= 1) + for _, rule in ipairs(moduleinfo.rules) do + modules = modules or {} + + local m = {} + + for _, provide in ipairs(rule.provides) do + m.provides = m.provides or {} + + assert(provide["logical-name"]) + if provide["compiled-module-path"] then + if not path.is_absolute(provide["compiled-module-path"]) then + m.provides[provide["logical-name"] ] = path.absolute(path.translate(provide["compiled-module-path"])) + else + m.provides[provide["logical-name"] ] = path.translate(provide["compiled-module-path"]) + end + else -- assume path with name + local name = provide["logical-name"] .. get_bmi_ext(target) + name:replace(":", "-") + + m.provides[provide["logical-name"] ] = { + bmi = path.join(cachedir, name), + sourcefile = moduleinfo.sourcefile + } + end + end + + assert(rule["primary-output"]) + modules[path.translate(rule["primary-output"])] = m + end + end + + for _, moduleinfo in ipairs(moduleinfos) do + for _, rule in ipairs(moduleinfo.rules) do + local m = modules[path.translate(rule["primary-output"])] + for _, r in ipairs(rule.requires) do + m.requires = m.requires or {} + + local p = r["source-path"] + if not p then + for _, dependency in pairs(modules) do + if dependency.provides and dependency.provides[r["logical-name"] ] then + p = dependency.provides[r["logical-name"] ].bmi + break + end + end + end + + m.requires[r["logical-name"] ] = { + method = r["lookup-method"] or "by-name", + path = p and path.translate(p) or nil, + unique = r["unique-on-source-path"] or false + } + end + end + end + + return modules +end + +function _topological_sort_visit(node, nodes, modules, output) + if node.marked then + return + end + + assert(not node.tempmarked) + + node.tempmarked = true + + local m1 = modules[node.objectfile] + + assert(m1.provides) + for _, n in ipairs(nodes) do + if not n.tempmarked then + local m2 = modules[n.objectfile] + + for name, provide in pairs(m1.provides) do + if m2.requires and m2.requires[name] then + _topological_sort_visit(n, nodes, modules, output) + end + end + end + end + + node.tempmarked = false + node.marked = true + + table.insert(output, 1, node.objectfile) +end + +function _topological_sort_has_node_without_mark(nodes) + for _, node in ipairs(nodes) do + if not node.marked then + return true + end + end + + return false +end + +function _topological_sort_get_first_unmarked_node(nodes) + for _, node in ipairs(nodes) do + if not node.marked and not node.tempmarked then + return node + end + end +end + +function sort_modules_by_dependencies(objectfiles, modules) + local output = {} + + local nodes = {} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m.provides then + table.append(nodes, { marked = false, tempmarked = false, objectfile = objectfile }) + end + end + + while _topological_sort_has_node_without_mark(nodes) do + local node = _topological_sort_get_first_unmarked_node(nodes) + + _topological_sort_visit(node, nodes, modules, output) + end + + return output +end + +function find_quote_header_file(target, sourcefile, file) + local p = path.join(path.directory(path.absolute(sourcefile, project.directory())), file) + + assert(os.isfile(p)) + + return p +end + +function find_angle_header_file(target, file) + -- check if the header is in subtarget + + local modules_support + if target:has_tool("cxx", "clang", "clangxx") then + modules_support = import("clang") + elseif target:has_tool("cxx", "gcc", "gxx") then + modules_support = import("gcc") + elseif target:has_tool("cxx", "cl") then + modules_support = import("msvc") + else + local _, toolname = target:tool("cxx") + raise("compiler(%s): does not support c++ module!", toolname) + end + + local headerpaths = modules_support.toolchain_include_directories(target) + + for _, dep in ipairs(target:orderdeps()) do + table.append(headerpaths, dep:scriptdir()) + end + + if project.required_packages then + for _, name in ipairs(target:get("packages")) do + local package = project.required_package(name) + table.join2(headerpaths, package:get("sysincludedirs")) + end + end + + table.join2(headerpaths, target:get("includedirs")) + + local p = find_file(file, headerpaths) + + assert(p) + assert(os.isfile(p)) + + return p +end + +function fallback_generate_dependencies(target, jsonfile, sourcefile) + local output = { + version = 0, + revision = 0, + rules = {} + } + + local rule = { + outputs = { + jsonfile + } + } + rule["primary-output"] = target:objectfile(sourcefile) + + local module_name + local module_deps = {} + local sourcecode = io.readfile(sourcefile) + sourcecode = sourcecode:gsub("//.-\n", "\n") + sourcecode = sourcecode:gsub("/%*.-%*/", "") + for _, line in ipairs(sourcecode:split("\n", {plain = true})) do + if not module_name then + module_name = line:match("export%s+module%s+(.+)%s*;") + end + + local module_depname = line:match("import%s+(.+)%s*;") + + if module_depname then + local module_dep = {} + + -- partition? import :xxx; + if module_depname:startswith(":") then + module_depname = module_name .. module_depname + elseif module_depname:startswith("\"") then + module_depname = module_depname:sub(2, -2) + module_dep["lookup-method"] = "include-quote" + module_dep["unique-on-source-path"] = true + module_dep["source-path"] = find_quote_header_file(target, sourcefile, module_depname) + elseif module_depname:startswith("<") then + module_depname = module_depname:sub(2, -2) + module_dep["lookup-method"] = "include-angle" + module_dep["unique-on-source-path"] = true + module_dep["source-path"] = find_angle_header_file(target, module_depname) + end + + module_dep["logical-name"] = module_depname + + table.insert(module_deps, module_dep) + end + end + + if module_name then + table.append(rule.outputs, module_name .. get_bmi_ext(target)) + + local provide = {} + provide["logical-name"] = module_name + provide["source-path"] = path.absolute(sourcefile, project.directory()) + + rule.provides = {} + table.append(rule.provides, provide) + end + + rule.requires = module_deps + + table.append(output.rules, rule) + + local jsondata = json.encode(output) + + io.writefile(jsonfile, jsondata) +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua new file mode 100644 index 000000000..5f66db54f --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -0,0 +1,259 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file gcc.lua +-- + +-- imports +import("core.tool.compiler") +import("core.project.project") +import("core.project.depend") +import("core.project.config") +import("utils.progress") +import("private.action.build.object", {alias = "objectbuilder"}) + +modulesflag = nil +modulemapperflag = nil +trtbdflag = nil + +function get_bmi_ext() + return ".gcm" +end + +-- get and create the path of module mapper +function get_module_mapper() + local mapper_file = path.join(config.buildir(), "mapper.txt") + if not os.isfile(mapper_file) then + io.writefile(mapper_file, "") + end + + return mapper_file +end + +-- add a module or header unit into the mapper +function add_module_to_mapper(file, module, bmi) + for line in io.lines(file) do + if line:startswith(module .. " ") then + return false + end + end + + local f = io.open(file, "a") + f:printf("%s %s\n", module, bmi) + f:close() + + return true +end + +-- load parent target with modules files +function load_parent(target, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + + target:add("cxxflags", modulesflag) + if os.isfile(get_module_mapper()) then + os.rm(get_module_mapper()) + end + target:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) +end + +-- check C++20 module support +function check_module_support(target) + local compinst = compiler.load("cxx", {target = target}) + + if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "gcc_modules_ts"}) then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + + if compinst:has_flags("-fmodule-mapper=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_module_mapper"}) then + modulemapperflag = "-fmodule-mapper=" + end + assert(modulemapperflag, "compiler(gcc): does not support c++ module!") + + if compinst:has_flags("-fdep-format=trtbd", "cxxflags", {flagskey = "gcc_dep_format"}) then + trtbdflag = "-fdep-format=trtbd" + end + + if compinst:has_flags("-fdep-file=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_dep_file"}) then + depfileflag = "-fdep-file=" + end + + if compinst:has_flags("-fdep-output=" .. os.tmpfile() .. ".o", "cxxflags", {flagskey = "gcc_dep_output"}) then + depoutputflag = "-fdep-output=" + end +end + +-- provide toolchain include dir for stl headerunit when p1689 is not supported +function toolchain_include_directories(target) + if is_plat("linux") then + return { "/usr/include/**", "/usr/local/include/**" } + end + + return {} +end + +-- generate dependency files +function generate_dependencies(target, sourcebatch, opt) + local common = import("common") + local cachedir = common.get_cache_dir(target) + local compinst = target:compiler("cxx") + local common_args = {"-E", "-x", "c++"} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function() + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + + if trtbdflag and depfileflag and depoutputflag then + local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) + local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) + + local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, depfileflag .. jsonfile, trtbdflag, depoutputfile .. target:objectfile(sourcefile), "-o", ifile} + + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + else + common.fallback_generate_dependencies(target, jsonfile, sourcefile) + end + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) + end +end + +-- generate target header units +function generate_headerunits(target, batchcmds, sourcebatch, opt) + local common = import("common") + + local compinst = target:compiler("cxx") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + local mapper_file = get_module_mapper() + + -- build headerunits + local objectfiles = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir + if headerunit.type == ":quote" then + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + else + outdir = path.join(cachedir, path.directory(headerunit.path)) + end + + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. get_bmi_ext() + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + local args = { "-c" } + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) + add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) + end + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + else + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + + if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if not os.isfile(bmifile) then + local args = { "-c", "-x", "c++-system-header", headerunit.name } + + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + end + end + + end +end + +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") + + local mapper_file = get_module_mapper() + local common_args = { "-x", "c++" } + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = { "-o", objectfile } + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + if add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then + table.join2(args, { "-c", provide.sourcefile }) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + target:add("objectfiles", objectfile) + end + end +end + diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua new file mode 100644 index 000000000..0a701e0f6 --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -0,0 +1,327 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file msvc.lua +-- + +-- imports +import("core.tool.compiler") +import("core.project.project") +import("core.project.depend") +import("utils.progress") +import("private.action.build.object", {alias = "objectbuilder"}) + +modulesflag = nil +ifcoutputflag = nil +ifcsearchdirflag = nil +interfaceflag = nil +referenceflag = nil +headernameflag = nil +headerunitflag = nil +exportheaderflag = nil +stdifcdirflag = nil +scandependenciesflag = nil +cxxsourcefileflag = "/TP" + +function get_bmi_ext() + return ".ifc" +end + +-- load parent target with modules files +function load_parent(target, opt) + local common = import("common") + -- get modules flag + local compinst = target:compiler("cxx") + + -- add module flags + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + 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 + + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") + if os.isdir(stdifcdir) then + target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false}) + end + end + break + end + 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 + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + return { path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "include") } + end + break + end + end + + assert(false) +end + +-- generate dependency files +function generate_dependencies(target, sourcebatch, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + + local common = import("common") + local cachedir = common.get_cache_dir(target) + local common_args = {cxxsourcefileflag, scandependenciesflag} + + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + 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()))) + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local jsonfile = path.join(outdir, path.filename(sourcefile) .. ".json") + + if scandependenciesflag then + local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} + + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + else + common.fallback_generate_dependencies(target, jsonfile, sourcefile) + end + + local dependinfo = io.readfile(jsonfile) + + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) + end +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") + + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) + + -- build headerunits + local common_args = {cxxsourcefileflag, exportheaderflag, "/c"} + local objectfiles = {} + local public_flags = {} + local private_flags = {} + for _, headerunit in ipairs(sourcebatch) do + if not headerunit.stl then + local file = path.relative(headerunit.path, target:scriptdir()) + + local objectfile = target:objectfile(file) + + local outdir + if headerunit.type == ":quote" then + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + else + outdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) + end + + if not os.isdir(outdir) then + os.mkdir(outdir) + end + + local bmifilename = path.basename(objectfile) .. get_bmi_ext() + + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outdir, "/Fo" .. objectfile} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} + table.join2(public_flags, flag) + target:add("objectfiles", objectfile) + else + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_ext()} + table.join2(private_flags, flag) + end + end + + return public_flags, private_flags +end + +-- build module files +function build_modules(target, batchcmds, objectfiles, modules, opt) + local cachedir = common.get_cache_dir(target) + + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + + -- 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} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + + if m then + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = {"/c", "/Fo" .. objectfile} + + local flag = {} + for name, provide in pairs(m.provides) do + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + + local bmifile = provide.bmi + table.join2(args, {interfaceflag, ifcoutputflag, bmifile, provide.sourcefile}) + + batchcmds:add_depfiles(provide.sourcefile) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + flag = {"/reference", name .. "=" .. path.filename(bmifile)} + end + + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args, bmi_args), {envs = vcvars}) + + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + target:add("cxxflags", flag, {force = true, expand = false}) + for _, f in ipairs(flag) do + target:data_add("cxx.modules.flags", f) + end + target:add("objectfiles", objectfile) + end + end +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 8992e3133..655a52d38 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -29,34 +29,30 @@ rule("c++.build.modules") local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false for _, dep in ipairs(target:orderdeps()) do - local modulefiles = dep:get("modulefiles") - if modulefiles and #modulefiles > 0 then - target_with_modules = target:sourcebatches()["c++.build.modules"] and true or target_with_modules - break - end + target_with_modules = dep:sourcebatches()["c++.build.modules"] and true or target_with_modules end if target_with_modules then target:set("policy", "build.across_targets_in_parallel", false) - -- import build_modules - local build_modules + -- import modules_support + local modules_support if target:has_tool("cxx", "clang", "clangxx") then - build_modules = import("build_modules.clang") + modules_support = import("modules_support.clang") elseif target:has_tool("cxx", "gcc", "gxx") then - build_modules = import("build_modules.gcc") + modules_support = import("modules_support.gcc") elseif target:has_tool("cxx", "cl") then - build_modules = import("build_modules.msvc") + modules_support = import("modules_support.msvc") else local _, toolname = target:tool("cxx") raise("compiler(%s): does not support c++ module!", toolname) end -- check C++20 module support - build_modules.check_module_support(target) + modules_support.check_module_support(target) -- load parent - build_modules.load_parent(target, opt) + modules_support.load_parent(target, opt) target:set("cxx.has_modules", true) end @@ -64,33 +60,30 @@ rule("c++.build.modules") rule("c++.build.modules.dependencies") - set_sourcekinds("cxx") - set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - before_build(function(target, opt) if not target:get("cxx.has_modules") then return end - local build_modules + local modules_support if target:has_tool("cxx", "clang", "clangxx") then - build_modules = import("build_modules.clang") + modules_support = import("modules_support.clang") elseif target:has_tool("cxx", "gcc", "gxx") then - build_modules = import("build_modules.gcc") + modules_support = import("modules_support.gcc") elseif target:has_tool("cxx", "cl") then - build_modules = import("build_modules.msvc") + modules_support = import("modules_support.msvc") else local _, toolname = target:tool("cxx") raise("compiler(%s): does not support c++ module!", toolname) end - local common = import("build_modules.common") + local common = import("modules_support.common") -- build dependency data - local batch = target:sourcebatches()["c++.build.modules.dependencies"] + local batch = target:sourcebatches()["c++.build.modules.builder"] common.patch_sourcebatch(target, batch, opt) - build_modules.generate_dependencies(target, batch, opt) + modules_support.generate_dependencies(target, batch, opt) local moduleinfos = common.load(target, batch, opt) local modules = common.parse_dependency_data(target, moduleinfos, opt) @@ -104,26 +97,25 @@ rule("c++.build.modules.builder") before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) if not target:get("cxx.has_modules") then + sourcebatch.objectfiles = {} return end - local build_modules + local modules_support if target:has_tool("cxx", "clang", "clangxx") then - build_modules = import("build_modules.clang") + modules_support = import("modules_support.clang") elseif target:has_tool("cxx", "gcc", "gxx") then - build_modules = import("build_modules.gcc") + modules_support = import("modules_support.gcc") elseif target:has_tool("cxx", "cl") then - build_modules = import("build_modules.msvc") + modules_support = import("modules_support.msvc") else local _, toolname = target:tool("cxx") raise("compiler(%s): does not support c++ module!", toolname) end - local common = import("build_modules.common") + local common = import("modules_support.common") local batch = sourcebatch - print(sourcebatch) - print(batch) batch.objectfiles = {} batch.dependfiles = {} @@ -151,7 +143,7 @@ rule("c++.build.modules.builder") local headerunits_flags local private_headerunits_flags if headerunits then - headerunits_flags, private_headerunits_flags = build_modules.generate_headerunits(target, batchcmds, headerunits, opt) + headerunits_flags, private_headerunits_flags = modules_support.generate_headerunits(target, batchcmds, headerunits, opt) end if headerunits_flags then @@ -166,14 +158,16 @@ rule("c++.build.modules.builder") -- topological sort local objectfiles = common.sort_modules_by_dependencies(batch.objectfiles, modules) - build_modules.build_modules(target, batchcmds, objectfiles, modules, opt) + modules_support.build_modules(target, batchcmds, objectfiles, modules, opt) end) -rules("c++.build.modules.install") +rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - on_config(function (target) + before_install(function (target) local sourcebatch = target:sourcebatches()["c++.build.modules.install"] - target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) - end \ No newline at end of file + if sourcebatch then + target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) + end + end) \ No newline at end of file -- cgit v1.3.1 From dcf5a1dfa3e592563093e862e0bb4ecd2ac3b3ba Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 02:36:31 +0200 Subject: [C++20 Modules] Add tests for headerunits --- tests/projects/c++/modules/stl_headerunit/src/hello.mpp | 11 +++++++++++ tests/projects/c++/modules/stl_headerunit/src/main.cpp | 6 ++++++ tests/projects/c++/modules/stl_headerunit/xmake.lua | 4 ++++ tests/projects/c++/modules/user_headerunit/src/header.hpp | 5 +++++ tests/projects/c++/modules/user_headerunit/src/hello.mpp | 10 ++++++++++ tests/projects/c++/modules/user_headerunit/src/main.cpp | 7 +++++++ tests/projects/c++/modules/user_headerunit/xmake.lua | 5 +++++ 7 files changed, 48 insertions(+) create mode 100644 tests/projects/c++/modules/stl_headerunit/src/hello.mpp create mode 100644 tests/projects/c++/modules/stl_headerunit/src/main.cpp create mode 100644 tests/projects/c++/modules/stl_headerunit/xmake.lua create mode 100644 tests/projects/c++/modules/user_headerunit/src/header.hpp create mode 100644 tests/projects/c++/modules/user_headerunit/src/hello.mpp create mode 100644 tests/projects/c++/modules/user_headerunit/src/main.cpp create mode 100644 tests/projects/c++/modules/user_headerunit/xmake.lua diff --git a/tests/projects/c++/modules/stl_headerunit/src/hello.mpp b/tests/projects/c++/modules/stl_headerunit/src/hello.mpp new file mode 100644 index 000000000..d45c5759e --- /dev/null +++ b/tests/projects/c++/modules/stl_headerunit/src/hello.mpp @@ -0,0 +1,11 @@ +module; + +export module hello; + +import ; + +export namespace hello { + void say(const char* str) { + std::cout << str << std::endl; + } +} diff --git a/tests/projects/c++/modules/stl_headerunit/src/main.cpp b/tests/projects/c++/modules/stl_headerunit/src/main.cpp new file mode 100644 index 000000000..1e5cc698f --- /dev/null +++ b/tests/projects/c++/modules/stl_headerunit/src/main.cpp @@ -0,0 +1,6 @@ +import hello; + +int main() { + hello::say("hello module!"); + return 0; +} diff --git a/tests/projects/c++/modules/stl_headerunit/xmake.lua b/tests/projects/c++/modules/stl_headerunit/xmake.lua new file mode 100644 index 000000000..e85378c46 --- /dev/null +++ b/tests/projects/c++/modules/stl_headerunit/xmake.lua @@ -0,0 +1,4 @@ +set_languages("c++20") +target("stl_headerunit") + set_kind("binary") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/user_headerunit/src/header.hpp b/tests/projects/c++/modules/user_headerunit/src/header.hpp new file mode 100644 index 000000000..15e522e15 --- /dev/null +++ b/tests/projects/c++/modules/user_headerunit/src/header.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace hello { + extern constexpr auto FOO = "Hello"; +} diff --git a/tests/projects/c++/modules/user_headerunit/src/hello.mpp b/tests/projects/c++/modules/user_headerunit/src/hello.mpp new file mode 100644 index 000000000..5b2f434ad --- /dev/null +++ b/tests/projects/c++/modules/user_headerunit/src/hello.mpp @@ -0,0 +1,10 @@ +module; +#include + +export module hello; + +export namespace hello { + void say(const char *arg) { + printf("%s\n", arg); + } +} diff --git a/tests/projects/c++/modules/user_headerunit/src/main.cpp b/tests/projects/c++/modules/user_headerunit/src/main.cpp new file mode 100644 index 000000000..ad786367e --- /dev/null +++ b/tests/projects/c++/modules/user_headerunit/src/main.cpp @@ -0,0 +1,7 @@ +import hello; +import "header.hpp"; + +int main() { + hello::say(hello::FOO); + return 0; +} diff --git a/tests/projects/c++/modules/user_headerunit/xmake.lua b/tests/projects/c++/modules/user_headerunit/xmake.lua new file mode 100644 index 000000000..dae91d11f --- /dev/null +++ b/tests/projects/c++/modules/user_headerunit/xmake.lua @@ -0,0 +1,5 @@ +set_languages("c++20") +target("user_headerunit") + set_kind("binary") + add_headerfiles("src/*.hpp") + add_files("src/*.cpp", "src/*.mpp") -- cgit v1.3.1 From d01b160c0e0f007ca0e8fc3c97ad47d3f79ace9c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 03:24:01 +0200 Subject: [C++20 Modules] Restore removed comments --- xmake/rules/c++/modules/xmake.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 655a52d38..f4b2498d7 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -33,6 +33,8 @@ rule("c++.build.modules") end if target_with_modules then + -- we disable to build across targets in parallel, because the source files may depend on other target modules + -- @see https://github.com/xmake-io/xmake/issues/1858 target:set("policy", "build.across_targets_in_parallel", false) -- import modules_support -- cgit v1.3.1 From fd7340759c71bd253da2d2ccaeede55fb57dfa24 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 03:24:25 +0200 Subject: [C++20] Improve target_with_modules detection --- xmake/rules/c++/modules/xmake.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index f4b2498d7..fd178f1d8 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -26,12 +26,19 @@ rule("c++.build.modules") add_deps("c++.build.modules.install") on_config(function (target) - local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false - - for _, dep in ipairs(target:orderdeps()) do - target_with_modules = dep:sourcebatches()["c++.build.modules"] and true or target_with_modules + function contains_modules(target) + local target_with_modules + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + target_with_modules = true + break + end + end + return target_with_modules end + local target_with_modules = target:sourcebatches()["c++.build.modules"] and contains_modules(target) or false if target_with_modules then -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 -- cgit v1.3.1 From da5627858bd40e911a8d5514a80613e35f5716e1 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 03:28:35 +0200 Subject: [C++20 Modules] Use a helper function to get module_builder --- xmake/rules/c++/modules/modules_support/common.lua | 15 ++++++++ xmake/rules/c++/modules/xmake.lua | 40 +++------------------- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 0bfcc7211..7df0b3d34 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -148,6 +148,21 @@ function get_bmi_ext(target) assert(false) end +function modules_support(target) + local module_builder + if target:has_tool("cxx", "clang", "clangxx") then + module_builder = import("clang", {anonymous = true}) + elseif target:has_tool("cxx", "gcc", "gxx") then + module_builder = import("gcc", {anonymous = true}) + elseif target:has_tool("cxx", "cl") then + module_builder = import("msvc", {anonymous = true}) + else + local _, toolname = target:tool("cxx") + raise("compiler(%s): does not support c++ module!", toolname) + end + return module_builder +end + function load(target, sourcebatch, opt) local cachedir = get_cache_dir(target) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index fd178f1d8..233fcab9f 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -44,18 +44,8 @@ rule("c++.build.modules") -- @see https://github.com/xmake-io/xmake/issues/1858 target:set("policy", "build.across_targets_in_parallel", false) - -- import modules_support - local modules_support - if target:has_tool("cxx", "clang", "clangxx") then - modules_support = import("modules_support.clang") - elseif target:has_tool("cxx", "gcc", "gxx") then - modules_support = import("modules_support.gcc") - elseif target:has_tool("cxx", "cl") then - modules_support = import("modules_support.msvc") - else - local _, toolname = target:tool("cxx") - raise("compiler(%s): does not support c++ module!", toolname) - end + local common = import("modules_support.common") + local modules_support = common.modules_support(target) -- check C++20 module support modules_support.check_module_support(target) @@ -74,19 +64,8 @@ rule("c++.build.modules.dependencies") return end - local modules_support - if target:has_tool("cxx", "clang", "clangxx") then - modules_support = import("modules_support.clang") - elseif target:has_tool("cxx", "gcc", "gxx") then - modules_support = import("modules_support.gcc") - elseif target:has_tool("cxx", "cl") then - modules_support = import("modules_support.msvc") - else - local _, toolname = target:tool("cxx") - raise("compiler(%s): does not support c++ module!", toolname) - end - local common = import("modules_support.common") + local modules_support = common.modules_support(target) -- build dependency data local batch = target:sourcebatches()["c++.build.modules.builder"] @@ -110,19 +89,8 @@ rule("c++.build.modules.builder") return end - local modules_support - if target:has_tool("cxx", "clang", "clangxx") then - modules_support = import("modules_support.clang") - elseif target:has_tool("cxx", "gcc", "gxx") then - modules_support = import("modules_support.gcc") - elseif target:has_tool("cxx", "cl") then - modules_support = import("modules_support.msvc") - else - local _, toolname = target:tool("cxx") - raise("compiler(%s): does not support c++ module!", toolname) - end - local common = import("modules_support.common") + local modules_support = common.modules_support(target) local batch = sourcebatch -- cgit v1.3.1 From e40e8ba4cb7c7b83fa9ef1a5fbdffe7708a8de02 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 03:30:03 +0200 Subject: [C++20 Modules] Restore removed comments --- xmake/rules/c++/modules/xmake.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 233fcab9f..be87a7eb0 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -26,6 +26,9 @@ rule("c++.build.modules") add_deps("c++.build.modules.install") on_config(function (target) + -- we disable to build across targets in parallel, because the source files may depend on other target modules + -- @see https://github.com/xmake-io/xmake/issues/1858 + function contains_modules(target) local target_with_modules for _, dep in ipairs(target:orderdeps()) do @@ -40,8 +43,10 @@ rule("c++.build.modules") local target_with_modules = target:sourcebatches()["c++.build.modules"] and contains_modules(target) or false if target_with_modules then - -- we disable to build across targets in parallel, because the source files may depend on other target modules - -- @see https://github.com/xmake-io/xmake/issues/1858 + -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, + -- even if some sub-targets do not contain C++ modules. + -- + -- maybe we will have a more fine-grained configuration strategy to disable it in the future. target:set("policy", "build.across_targets_in_parallel", false) local common = import("modules_support.common") -- cgit v1.3.1 From a9ed54fd3af64a04bb7d617a51dde689d23c80de Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 03:32:16 +0200 Subject: [C++20 Modules] Move contains_modules function into common.lua --- xmake/rules/c++/modules/modules_support/common.lua | 12 ++++++++++++ xmake/rules/c++/modules/xmake.lua | 17 ++--------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 7df0b3d34..ca637cbf2 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -163,6 +163,18 @@ function modules_support(target) return module_builder end +function contains_modules(target) + local target_with_modules + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + target_with_modules = true + break + end + end + return target_with_modules +end + function load(target, sourcebatch, opt) local cachedir = get_cache_dir(target) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index be87a7eb0..436d7c5e2 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -28,20 +28,9 @@ rule("c++.build.modules") on_config(function (target) -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 + local common = import("modules_support.common") - function contains_modules(target) - local target_with_modules - for _, dep in ipairs(target:orderdeps()) do - local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then - target_with_modules = true - break - end - end - return target_with_modules - end - - local target_with_modules = target:sourcebatches()["c++.build.modules"] and contains_modules(target) or false + local target_with_modules = target:sourcebatches()["c++.build.modules"] and common.contains_modules(target) or false if target_with_modules then -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, -- even if some sub-targets do not contain C++ modules. @@ -49,7 +38,6 @@ rule("c++.build.modules") -- maybe we will have a more fine-grained configuration strategy to disable it in the future. target:set("policy", "build.across_targets_in_parallel", false) - local common = import("modules_support.common") local modules_support = common.modules_support(target) -- check C++20 module support @@ -148,7 +136,6 @@ rule("c++.build.modules.install") before_install(function (target) local sourcebatch = target:sourcebatches()["c++.build.modules.install"] - if sourcebatch then target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) end -- cgit v1.3.1 From 728126bd7816bbd5fb6b93cedc7163a425343fba Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 3 Aug 2022 04:10:04 +0200 Subject: [C++20 Modules] Improve support --- xmake/rules/c++/modules/modules_support/clang.lua | 260 ++++++++++++------ xmake/rules/c++/modules/modules_support/common.lua | 23 +- xmake/rules/c++/modules/modules_support/gcc.lua | 145 ++++++---- xmake/rules/c++/modules/modules_support/msvc.lua | 292 +++++++++++++-------- xmake/rules/c++/modules/xmake.lua | 25 +- 5 files changed, 490 insertions(+), 255 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index e12c7afed..49dbee0a2 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -25,35 +25,16 @@ import("core.project.depend") import("core.project.config") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) - -modulesflag = nil -modulestsflag = nil -implicitmodules = nil -implicitmodulemapsflag = nil -prebuiltmodulepathflag = nil - -function get_bmi_ext() - return ".pcm" -end +import("common") -- load parent target with modules files function load_parent(target, opt) - local common = import("common") local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) - -- add module flags - target:add("cxxflags", modulesflag or modulestsflag) - - -- add the module cache directory - target:add("cxxflags", implicitmodulesflag, {force = true}) - target:add("cxxflags", implicitmodulemapsflag, {force = true}) - - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) for _, dep in ipairs(target:orderdeps()) do cachedir = common.get_cache_dir(dep) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) end end @@ -61,68 +42,57 @@ end -- check C++20 module support function check_module_support(target) local compinst = compiler.load("cxx", {target = target}) + local cachedir = common.get_cache_dir(target) + local stlcachedir = common.get_stlcache_dir(target) - if compinst:has_flags("-fmodules", "cxxflags", {flagskey = "clang_modules"}) then - modulesflag = "-fmodules" - end - - if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "clang_modules_ts"}) then - modulestsflag = "-fmodules-ts" - end - assert(modulesflag or modulestsflag, "compiler(clang): does not support c++ module!") - - if compinst:has_flags((modulesflag or modulestsflag) .. " -fimplicit-modules", "cxxflags", {flagskey = "clang_implicit_modules"}) then - implicitmodulesflag = "-fimplicit-modules" - end - assert(implicitmodulesflag, "compiler(clang): does not support c++ module!") - - if compinst:has_flags((modulesflag or modulestsflag) .. " -fimplicit-module-maps" .. os.tmpdir(), "cxxflags", {flagskey = "clang_implicit_module_path"}) then - implicitmodulemapsflag = "-fimplicit-module-maps" - end - assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") - - if compinst:has_flags((modulesflag or modulestsflag) .. " -fprebuilt-module-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_prebuild_module_path"}) then - prebuiltmodulepathflag = "-fprebuilt-module-path=" - end - assert(prebuiltmodulepathflag, "compiler(clang): does not support c++ module!") + -- get module and module cache flags + local modulesflag = get_modulesflag(target) + local implicitmodulesflag = get_implicitmodulesflag(target) + local implicitmodulemapsflag = get_implicitmodulemapsflag(target) + local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) - if compinst:has_flags((modulesflag or modulestsflag) .. " -fmodules-cache-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_modules_cache_path"}) then - modulecachepathflag = "-fmodules-cache-path=" - end - assert(modulecachepathflag, "compiler(clang): does not support c++ module!") - - if compinst:has_flags((modulesflag or modulestsflag) .. " -emit-module", "cxxflags", {flagskey = "clang_emit_module"}) then - emitmoduleflag = " -emit-module" - end - assert(emitmoduleflag, "compiler(clang): does not support c++ module!") + -- add module flags + target:add("cxxflags", modulesflag) - if compinst:has_flags((modulesflag or modulestsflag) .. " -fmodule-file=" .. os.tmpfile() .. get_bmi_ext(), "cxxflags", {flagskey = "clang_module_file"}) then - modulefileflag = "-fmodule-file=" - end - assert(modulefileflag, "compiler(clang): does not support c++ module!") + -- add the module cache directory + target:add("cxxflags", implicitmodulesflag, {force = true}) + target:add("cxxflags", implicitmodulemapsflag, {force = true}) - if compinst:has_flags((modulesflag or modulestsflag) .. " -emit-module-interface", "cxxflags", {flagskey = "clang_emit_module_interface"}) then - emitmoduleinterfaceflag = "-emit-module-interface" - end - assert(emitmoduleinterfaceflag, "compiler(clang): does not support c++ module!") + target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) end function toolchain_include_directories(target) - if is_plat("linux") then - return { "/usr/include/**", "/usr/local/include/**" } - end + local includedirs = _g.includedirs + if includedirs == nil then + includedirs = {} - return {} + local gcc, toolname = target:tool("cc") + assert(toolname, "clang") + + local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if os.isdir(line) then + table.append(includedirs, line) + break + elseif line:startswith("End") then + break + end + end + end + _g.includedirs = includedirs or {} + end + return includedirs end function generate_dependencies(target, sourcebatch, opt) - local common = import("common") local cachedir = common.get_cache_dir(target) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) if not os.isdir(outdir) then @@ -143,13 +113,17 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) - local common = import("common") - local compinst = target:compiler("cxx") - local cachedir = common.get_cache_dir(target) local stlcachedir = common.get_stlcache_dir(target) + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + + -- get headerunits flags + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleflag = get_emitmoduleflag(target) + local modulefileflag = get_modulefileflag(target) + -- build headerunits local objectfiles = {} local public_flags = {} @@ -210,15 +184,18 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.append(private_flags, modulefileflag .. bmifile) end end - return public_flags, private_flags end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) - local compinst = target:compiler("cxx") + local cachedir = common.get_cache_dir(target) + + -- get modules flags + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) + local modulefileflag = get_modulefileflag(target) -- append deps modules local flags = {} @@ -268,3 +245,140 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end end + +function get_bmi_ext() + return ".pcm" +end + +function get_modulesflag(target) + local modulesflag = _g.modulesflag + if modulesflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fmodules", "cxxflags", {flagskey = "clang_modules"}) then + modulesflag = "-fmodules" + end + + if not modulesflag then + if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "clang_modules_ts"}) then + modulesflag = "-fmodules-ts" + end + end + + assert(modulesflag, "compiler(clang): does not support c++ module!") + + _g.modulesflag = modulesflag or false + end + return modulesflag +end + +function get_implicitmodulesflag(target) + local implicitmodulesflag = _g.implicitmodulesflag + if implicitmodulesflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fimplicit-modules", "cxxflags", {flagskey = "clang_implicit_modules"}) then + implicitmodulesflag = "-fimplicit-modules" + end + assert(implicitmodulesflag, "compiler(clang): does not support c++ module!") + + _g.implicitmodulesflag = implicitmodulesflag or false + end + return implicitmodulesflag +end + +function get_implicitmodulemapsflag(target) + local implicitmodulemapsflag = _g.implicitmodulemapsflag + if implicitmodulemapsflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fimplicit-module-maps", "cxxflags", {flagskey = "clang_implicit_module_maps"}) then + implicitmodulemapsflag = "-fimplicit-module-maps" + end + assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") + + _g.implicitmodulemapsflag = implicitmodulemapsflag or false + end + return implicitmodulemapsflag +end + +function get_prebuiltmodulepathflag(target) + local prebuiltmodulepathflag = _g.prebuiltmodulepathflag + if prebuiltmodulepathflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fprebuilt-module-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_prebuild_module_path"}) then + prebuiltmodulepathflag = "-fprebuilt-module-path=" + end + assert(prebuiltmodulepathflag, "compiler(clang): does not support c++ module!") + + _g.prebuiltmodulepathflag = prebuiltmodulepathflag or false + end + return prebuiltmodulepathflag +end + +function get_modulecachepathflag(target) + local modulecachepathflag = _g.modulecachepathflag + if modulecachepathflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fmodules-cache-path=" .. os.tmpdir(), "cxxflags", {flagskey = "clang_modules_cache_path"}) then + modulecachepathflag = "-fmodules-cache-path=" + end + assert(modulecachepathflag, "compiler(clang): does not support c++ module!") + + _g.modulecachepathflag = modulecachepathflag or false + end + return modulecachepathflag +end + +function get_emitmoduleflag(target) + local emitmoduleflag = _g.emitmoduleflag + if emitmoduleflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-emit-module", "cxxflags", {flagskey = "clang_emit_module"}) then + emitmoduleflag = " -emit-module" + end + assert(emitmoduleflag, "compiler(clang): does not support c++ module!") + + _g.emitmoduleflag = emitmoduleflag or false + end + return emitmoduleflag +end + +function get_modulefileflag(target) + local modulefileflag = _g.modulefileflag + if modulefileflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fmodule-file=" .. os.tmpfile() .. get_bmi_ext(), "cxxflags", {flagskey = "clang_module_file"}) then + modulefileflag = "-fmodule-file=" + end + assert(modulefileflag, "compiler(clang): does not support c++ module!") + + _g.modulefileflag = modulefileflag or false + end + return modulefileflag +end + +function get_emitmoduleinterfaceflag(target) + local emitmoduleinterfaceflag = _g.emitmoduleinterfaceflag + if emitmoduleinterfaceflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-emit-module-interface", "cxxflags", {flagskey = "clang_emit_module_interface"}) then + emitmoduleinterfaceflag = "-emit-module-interface" + end + assert(emitmoduleinterfaceflag, "compiler(clang): does not support c++ module!") + + _g.emitmoduleinterfaceflag = emitmoduleinterfaceflag or false + end + return emitmoduleinterfaceflag +end + +function has_headerunitsupport(target) + local support_headerunits = _g.support_headerunits + if support_headerunits == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support"}) and + compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support"}) then + support_headerunits = true + end + + _g.support_headerunits = support_headerunits or false + end + return support_headerunits +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index ca637cbf2..e706f4e81 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -1,10 +1,11 @@ import("core.base.json") +import("core.base.hashset") import("core.project.config") import("core.tool.compiler") import("core.project.project") import("lib.detect.find_file") -local stl_headers = { +_g.stl_headers = { "algorithm", "forward_list", "numbers", @@ -86,17 +87,11 @@ local stl_headers = { "stdexcept"} function get_stl_headers() - return stl_headers + return hashset.from(_g.stl_headers) end function is_stl_header(header) - for _, stl_header in ipairs(stl_headers) do - if stl_header == header then - return true - end - end - - return false + return get_stl_headers():has(header) end function get_stlcache_dir(target) @@ -107,7 +102,6 @@ function get_stlcache_dir(target) if not os.isdir(stlcachedir) then os.mkdir(stlcachedir) end - return path.translate(stlcachedir) end @@ -116,7 +110,6 @@ function get_cache_dir(target) if not os.isdir(cachedir) then os.mkdir(cachedir) end - return path.translate(cachedir) end @@ -133,7 +126,6 @@ function patch_sourcebatch(target, sourcebatch, opt) table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, dependfile) end - end function get_bmi_ext(target) @@ -144,7 +136,6 @@ function get_bmi_ext(target) elseif target:has_tool("cxx", "clang", "clangxx") then return import("clang").get_bmi_ext() end - assert(false) end @@ -164,7 +155,8 @@ function modules_support(target) end function contains_modules(target) - local target_with_modules + local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false + for _, dep in ipairs(target:orderdeps()) do local sourcebatches = dep:sourcebatches() if sourcebatches and sourcebatches["c++.build.modules"] then @@ -195,7 +187,6 @@ function load(target, sourcebatch, opt) end end end - return moduleinfos end @@ -260,7 +251,6 @@ function parse_dependency_data(target, moduleinfos, opt) end end end - return modules end @@ -329,7 +319,6 @@ function sort_modules_by_dependencies(objectfiles, modules) _topological_sort_visit(node, nodes, modules, output) end - return output end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 5f66db54f..0c8027b6e 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -25,14 +25,7 @@ import("core.project.depend") import("core.project.config") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) - -modulesflag = nil -modulemapperflag = nil -trtbdflag = nil - -function get_bmi_ext() - return ".gcm" -end +import("common") -- get and create the path of module mapper function get_module_mapper() @@ -53,7 +46,7 @@ function add_module_to_mapper(file, module, bmi) end local f = io.open(file, "a") - f:printf("%s %s\n", module, bmi) + f:print("%s %s", module, bmi) f:close() return true @@ -61,63 +54,63 @@ end -- load parent target with modules files function load_parent(target, opt) - local common = import("common") - local cachedir = common.get_cache_dir(target) - - target:add("cxxflags", modulesflag) - if os.isfile(get_module_mapper()) then - os.rm(get_module_mapper()) - end - target:add("cxxflags", "-fmodule-mapper=" .. get_module_mapper(), {force = true, expand = false}) end -- check C++20 module support function check_module_support(target) local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "gcc_modules_ts"}) then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(gcc): does not support c++ module!") + local modulesflag = get_modulesflag(target) + local modulemapperflag = get_modulemapperflag(target) - if compinst:has_flags("-fmodule-mapper=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_module_mapper"}) then - modulemapperflag = "-fmodule-mapper=" - end - assert(modulemapperflag, "compiler(gcc): does not support c++ module!") - - if compinst:has_flags("-fdep-format=trtbd", "cxxflags", {flagskey = "gcc_dep_format"}) then - trtbdflag = "-fdep-format=trtbd" - end - - if compinst:has_flags("-fdep-file=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_dep_file"}) then - depfileflag = "-fdep-file=" - end + target:add("cxxflags", modulesflag) - if compinst:has_flags("-fdep-output=" .. os.tmpfile() .. ".o", "cxxflags", {flagskey = "gcc_dep_output"}) then - depoutputflag = "-fdep-output=" + if os.isfile(get_module_mapper()) then + os.rm(get_module_mapper()) end + target:add("cxxflags", modulemapperflag .. get_module_mapper(), {force = true, expand = false}) end -- provide toolchain include dir for stl headerunit when p1689 is not supported function toolchain_include_directories(target) - if is_plat("linux") then - return { "/usr/include/**", "/usr/local/include/**" } - end - - return {} + local includedirs = _g.includedirs + if includedirs == nil then + includedirs = {} + + local gcc, toolname = target:tool("cc") + assert(toolname, "gcc") + + local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if os.isdir(line) then + table.append(includedirs, line) + break + elseif line:startswith("End") then + break + end + end + end + _g.includedirs = includedirs or {} + end + return includedirs end -- generate dependency files function generate_dependencies(target, sourcebatch, opt) - local common = import("common") local cachedir = common.get_cache_dir(target) local compinst = target:compiler("cxx") local common_args = {"-E", "-x", "c++"} + local trtbdflag = get_trtbdflag(target) + local depfileflag = get_depfileflag(target) + local depoutputflag = get_depoutputflag(target) + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) if not os.isdir(outdir) then @@ -146,8 +139,6 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) - local common = import("common") - local compinst = target:compiler("cxx") local cachedir = common.get_cache_dir(target) @@ -213,7 +204,6 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) end end end - end end @@ -257,3 +247,68 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end +function get_bmi_ext() + return ".gcm" +end + +function get_modulesflag(target) + local modulesflag = _g.modulesflag + if modulesflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "gcc_modules_ts"}) then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + _g.modulesflag = modulesflag or false + end + return modulesflag +end + +function get_modulemapperflag(target) + local modulemapperflag = _g.modulemapperflag + if modulemapperflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fmodule-mapper=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_module_mapper"}) then + modulemapperflag = "-fmodule-mapper=" + end + assert(modulemapperflag, "compiler(gcc): does not support c++ module!") + _g.modulemapperflag = modulemapperflag or false + end + return modulemapperflag +end + +function get_trtbdflag(target) + local trtbdflag = _g.trtbdflag + if trtbdflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fdep-format=trtbd", "cxxflags", {flagskey = "gcc_dep_format"}) then + trtbdflag = "-fdep-format=trtbd" + end + _g.trtbdflag = trtbdflag or false + end + return trtbdflag +end + +function get_depfileflag(target) + local depfileflag = _g.depfileflag + if depfileflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fdep-file=" .. os.tmpfile(), "cxxflags", {flagskey = "gcc_dep_file"}) then + depfileflag = "-fdep-file=" + end + _g.depfileflag = depfileflag or false + end + return depfileflag +end + +function get_depoutputflag(target) + local depoutputflag = _g.depoutputflag + if depoutputflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fdep-output=" .. os.tmpfile() .. ".o", "cxxflags", {flagskey = "gcc_dep_output"}) then + depoutputflag = "-fdep-output=" + end + _g.depoutputflag = depoutputflag or false + end + return depoutputflag +end 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 diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 436d7c5e2..313d932f9 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -26,38 +26,39 @@ rule("c++.build.modules") add_deps("c++.build.modules.install") on_config(function (target) + import("modules_support.common") + -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 - local common = import("modules_support.common") - - local target_with_modules = target:sourcebatches()["c++.build.modules"] and common.contains_modules(target) or false - if target_with_modules then + if common.contains_modules(target) then -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, -- even if some sub-targets do not contain C++ modules. -- -- maybe we will have a more fine-grained configuration strategy to disable it in the future. target:set("policy", "build.across_targets_in_parallel", false) + -- get modules support local modules_support = common.modules_support(target) -- check C++20 module support modules_support.check_module_support(target) + -- mark this target with modules + target:data_set("cxx.has_modules", true) + -- load parent modules_support.load_parent(target, opt) - - target:set("cxx.has_modules", true) end end) rule("c++.build.modules.dependencies") before_build(function(target, opt) - if not target:get("cxx.has_modules") then + if not target:data("cxx.has_modules") then return end - local common = import("modules_support.common") + import("modules_support.common") local modules_support = common.modules_support(target) -- build dependency data @@ -77,12 +78,12 @@ rule("c++.build.modules.builder") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) - if not target:get("cxx.has_modules") then + if not target:data("cxx.has_modules") then sourcebatch.objectfiles = {} return end - local common = import("modules_support.common") + import("modules_support.common") local modules_support = common.modules_support(target) local batch = sourcebatch @@ -135,6 +136,10 @@ rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") before_install(function (target) + if not target:data("cxx.has_modules") then + return + end + local sourcebatch = target:sourcebatches()["c++.build.modules.install"] if sourcebatch then target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) -- cgit v1.3.1 From e387de53870b6ac9432a6599d9904910b088bc7c Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 3 Aug 2022 23:54:18 +0800 Subject: remove tailing spaces --- xmake/rules/c++/modules/modules_support/clang.lua | 38 ++++++++--------- xmake/rules/c++/modules/modules_support/common.lua | 20 ++++----- xmake/rules/c++/modules/modules_support/gcc.lua | 48 +++++++++++----------- xmake/rules/c++/modules/modules_support/msvc.lua | 14 +++---- xmake/rules/c++/modules/xmake.lua | 6 +-- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 49dbee0a2..666eb2135 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -62,34 +62,34 @@ function check_module_support(target) end function toolchain_include_directories(target) - local includedirs = _g.includedirs - if includedirs == nil then + local includedirs = _g.includedirs + if includedirs == nil then includedirs = {} - local gcc, toolname = target:tool("cc") - assert(toolname, "clang") - - local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} - if result then - for _, line in ipairs(result:split("\n", {plain = true})) do - line = line:trim() - if os.isdir(line) then + local gcc, toolname = target:tool("cc") + assert(toolname, "clang") + + local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if os.isdir(line) then table.append(includedirs, line) - break - elseif line:startswith("End") then - break - end - end + break + elseif line:startswith("End") then + break + end + end end _g.includedirs = includedirs or {} - end + end return includedirs end function generate_dependencies(target, sourcebatch, opt) local cachedir = common.get_cache_dir(target) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) @@ -229,7 +229,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depcache(target:dependfile(bmifile)) table.join2(flag, { modulefileflag .. bmifile }) - end + end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles, {"-c", "-o", objectfile})) @@ -381,4 +381,4 @@ function has_headerunitsupport(target) _g.support_headerunits = support_headerunits or false end return support_headerunits -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index e706f4e81..176d89c4b 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -88,7 +88,7 @@ _g.stl_headers = { function get_stl_headers() return hashset.from(_g.stl_headers) -end +end function is_stl_header(header) return get_stl_headers():has(header) @@ -120,7 +120,7 @@ function patch_sourcebatch(target, sourcebatch, opt) sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) table.insert(sourcebatch.objectfiles, objectfile) @@ -215,9 +215,9 @@ function parse_dependency_data(target, moduleinfos, opt) local name = provide["logical-name"] .. get_bmi_ext(target) name:replace(":", "-") - m.provides[provide["logical-name"] ] = { - bmi = path.join(cachedir, name), - sourcefile = moduleinfo.sourcefile + m.provides[provide["logical-name"] ] = { + bmi = path.join(cachedir, name), + sourcefile = moduleinfo.sourcefile } end end @@ -250,7 +250,7 @@ function parse_dependency_data(target, moduleinfos, opt) } end end - end + end return modules end @@ -306,7 +306,7 @@ function sort_modules_by_dependencies(objectfiles, modules) local output = {} local nodes = {} - for _, objectfile in ipairs(objectfiles) do + for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m.provides then @@ -332,7 +332,7 @@ end function find_angle_header_file(target, file) -- check if the header is in subtarget - + local modules_support if target:has_tool("cxx", "clang", "clangxx") then modules_support = import("clang") @@ -420,7 +420,7 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) if module_name then table.append(rule.outputs, module_name .. get_bmi_ext(target)) - + local provide = {} provide["logical-name"] = module_name provide["source-path"] = path.absolute(sourcefile, project.directory()) @@ -436,4 +436,4 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) local jsondata = json.encode(output) io.writefile(jsonfile, jsondata) -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 0c8027b6e..db29c1bef 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -73,27 +73,27 @@ end -- provide toolchain include dir for stl headerunit when p1689 is not supported function toolchain_include_directories(target) - local includedirs = _g.includedirs - if includedirs == nil then + local includedirs = _g.includedirs + if includedirs == nil then includedirs = {} - - local gcc, toolname = target:tool("cc") - assert(toolname, "gcc") - - local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} - if result then - for _, line in ipairs(result:split("\n", {plain = true})) do - line = line:trim() - if os.isdir(line) then + + local gcc, toolname = target:tool("cc") + assert(toolname == "gcc") + + local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if os.isdir(line) then table.append(includedirs, line) - break - elseif line:startswith("End") then - break - end - end - end + break + elseif line:startswith("End") then + break + end + end + end _g.includedirs = includedirs or {} - end + end return includedirs end @@ -107,7 +107,7 @@ function generate_dependencies(target, sourcebatch, opt) local depfileflag = get_depfileflag(target) local depoutputflag = get_depoutputflag(target) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) @@ -124,9 +124,9 @@ function generate_dependencies(target, sourcebatch, opt) local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, depfileflag .. jsonfile, trtbdflag, depoutputfile .. target:objectfile(sourcefile), "-o", ifile} - + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - else + else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end @@ -154,7 +154,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) local objectfile = target:objectfile(file) - local outdir + local outdir if headerunit.type == ":quote" then outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) else @@ -210,7 +210,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local cachedir = common.get_cache_dir(target) - + local compinst = target:compiler("cxx") local mapper_file = get_module_mapper() @@ -235,7 +235,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) end - end + end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 1851d678c..ca7ca19e7 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -90,9 +90,9 @@ function generate_dependencies(target, sourcebatch, opt) local scandependenciesflag = get_scandependenciesflag(target) local cachedir = common.get_cache_dir(target) - local common_args = {"/TP", scandependenciesflag} + local common_args = {"/TP", scandependenciesflag} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function () progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) @@ -106,7 +106,7 @@ function generate_dependencies(target, sourcebatch, opt) if scandependenciesflag then local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} - + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) @@ -117,7 +117,7 @@ function generate_dependencies(target, sourcebatch, opt) return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end -end +end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) @@ -198,7 +198,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local cachedir = common.get_cache_dir(target) - + local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -237,7 +237,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depcache(target:dependfile(bmifile)) flag = {referenceflag, name .. "=" .. path.filename(bmifile)} - end + end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args, bmi_args), {envs = vcvars}) @@ -339,7 +339,7 @@ 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 + 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 diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 313d932f9..785e8fed5 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,7 +53,7 @@ rule("c++.build.modules") rule("c++.build.modules.dependencies") - before_build(function(target, opt) + before_build(function(target, opt) if not target:data("cxx.has_modules") then return end @@ -141,7 +141,7 @@ rule("c++.build.modules.install") end local sourcebatch = target:sourcebatches()["c++.build.modules.install"] - if sourcebatch then + if sourcebatch then target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) end - end) \ No newline at end of file + end) -- cgit v1.3.1 From 533fa58d9ed5c4fe63017342b3eba282ac72f12e Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:43:07 +0800 Subject: format some codes --- xmake/rules/c++/modules/xmake.lua | 64 ++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 785e8fed5..0c0f8cac9 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,6 +21,7 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + add_deps("c++.build.modules.dependencies") add_deps("c++.build.modules.builder") add_deps("c++.build.modules.install") @@ -51,28 +52,29 @@ rule("c++.build.modules") end end) - +-- build dependencies rule("c++.build.modules.dependencies") before_build(function(target, opt) if not target:data("cxx.has_modules") then return end + -- patch sourcebatch import("modules_support.common") - local modules_support = common.modules_support(target) - - -- build dependency data - local batch = target:sourcebatches()["c++.build.modules.builder"] - common.patch_sourcebatch(target, batch, opt) + local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] + common.patch_sourcebatch(target, sourcebatch, opt) - modules_support.generate_dependencies(target, batch, opt) + -- generate dependencies + local modules_support = common.modules_support(target) + modules_support.generate_dependencies(target, sourcebatch, opt) - local moduleinfos = common.load(target, batch, opt) + -- load and parse module dependencies + local moduleinfos = common.load(target, sourcebatch, opt) local modules = common.parse_dependency_data(target, moduleinfos, opt) - target:data_set("cxx.modules", modules) end) +-- build modules rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") @@ -83,27 +85,23 @@ rule("c++.build.modules.builder") return end + -- patch sourcebatch import("modules_support.common") - local modules_support = common.modules_support(target) - - local batch = sourcebatch - - batch.objectfiles = {} - batch.dependfiles = {} - common.patch_sourcebatch(target, batch, opt) - - local modules = target:data("cxx.modules") + sourcebatch.objectfiles = {} + sourcebatch.dependfiles = {} + common.patch_sourcebatch(target, sourcebatch, opt) + -- get headerunits info, TODO maybe need optimize it local headerunits - for _, objectfile in ipairs(batch.objectfiles) do + local modules = target:data("cxx.modules") + for _, objectfile in ipairs(sourcebatch.objectfiles) do for obj, m in pairs(modules) do if obj == objectfile then for name, r in pairs(m.requires) do if r.method ~= "by-name" then headerunits = headerunits or {} - - local type = r.method == "include-angle" and ":angle" or ":quote" - table.append(headerunits, { name = name, path = r.path, type = type, stl = common.is_stl_header(name) }) + local unittype = r.method == "include-angle" and ":angle" or ":quote" + table.append(headerunits, {name = name, path = r.path, type = unittype, stl = common.is_stl_header(name)}) end end break @@ -111,12 +109,13 @@ rule("c++.build.modules.builder") end end + -- generate headerunits local headerunits_flags local private_headerunits_flags + local modules_support = common.modules_support(target) if headerunits then headerunits_flags, private_headerunits_flags = modules_support.generate_headerunits(target, batchcmds, headerunits, opt) end - if headerunits_flags then target:add("cxxflags", headerunits_flags, {force = true, expand = false}) end @@ -124,24 +123,21 @@ rule("c++.build.modules.builder") target:add("cxxflags", private_headerunits_flags, {force = true, expand = false}) end - local modules = target:data("cxx.modules") - -- topological sort - local objectfiles = common.sort_modules_by_dependencies(batch.objectfiles, modules) - + local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) modules_support.build_modules(target, batchcmds, objectfiles, modules, opt) end) +-- install modules rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") before_install(function (target) - if not target:data("cxx.has_modules") then - return - end - - local sourcebatch = target:sourcebatches()["c++.build.modules.install"] - if sourcebatch then - target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) + import("modules_support.common") + if common.contains_modules(target) then + local sourcebatch = target:sourcebatches()["c++.build.modules.install"] + if sourcebatch then + target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"}) + end end end) -- cgit v1.3.1 From 553bb39bd9a0394a19e0c23706611533ef2f8fa3 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:43:24 +0800 Subject: add some comments --- xmake/rules/c++/modules/xmake.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 0c0f8cac9..a46947a53 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -134,6 +134,9 @@ rule("c++.build.modules.install") before_install(function (target) import("modules_support.common") + + -- we cannot use target:data("cxx.has_modules"), + -- because on_config will be not called when installing targets if common.contains_modules(target) then local sourcebatch = target:sourcebatches()["c++.build.modules.install"] if sourcebatch then -- cgit v1.3.1 From 110a916cfc9e9a95bc2c3784725cb47c3fd1c762 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:45:46 +0800 Subject: add stl headers --- xmake/rules/c++/modules/modules_support/common.lua | 110 ++++--------------- .../c++/modules/modules_support/stl_headers.lua | 122 +++++++++++++++++++++ xmake/rules/c++/modules/xmake.lua | 3 +- 3 files changed, 145 insertions(+), 90 deletions(-) create mode 100644 xmake/rules/c++/modules/modules_support/stl_headers.lua diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 176d89c4b..b86ad8f1f 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -1,3 +1,24 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author Arthapz, ruki +-- @file common.lua +-- + +-- imports import("core.base.json") import("core.base.hashset") import("core.project.config") @@ -5,95 +26,6 @@ import("core.tool.compiler") import("core.project.project") import("lib.detect.find_file") -_g.stl_headers = { - "algorithm", - "forward_list", - "numbers", - "stop_token", - "any", - "fstream", - "numeric", - "streambuf", - "array", - "functional", - "optional", - "string", - "atomic", - "future", - "ostream", - "string_view", - "barrier", - "initializer_list", - "queue", - "bit", - "iomanip", - "random", - "syncstream", - "bitset", - "ios", - "ranges", - "system_error", - "charconv", - "iosfwd", - "ratio", - "thread", - "chrono", - "iostream", - "regex", - "tuple", - "codecvt", - "istream", - "scoped_allocator", - "typeindex", - "compare", - "iterator", - "semaphore", - "typeinfo", - "complex", - "latch", - "set", - "type_traits", - "concepts", - "limits", - "shared_mutex", - "unordered_map", - "condition_variable", - "list", - "source_location", - "unordered_set", - "coroutine", - "locale", - "span", - "utility", - "deque", - "map", - "spanstream", - "valarray", - "exception", - "memory", - "sstream", - "variant", - "execution", - "memory_resource", - "stack", - "vector", - "filesystem", - "mutex", - "version", - "format", - "new", - "type_traits", - "string_view", - "stdexcept"} - -function get_stl_headers() - return hashset.from(_g.stl_headers) -end - -function is_stl_header(header) - return get_stl_headers():has(header) -end - function get_stlcache_dir(target) local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") if target:has_tool("cxx", "clang", "clangxx") then diff --git a/xmake/rules/c++/modules/modules_support/stl_headers.lua b/xmake/rules/c++/modules/modules_support/stl_headers.lua new file mode 100644 index 000000000..aa5cb497c --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/stl_headers.lua @@ -0,0 +1,122 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author Arthapz, ruki +-- @file stl_headers.lua +-- + +-- imports +import("core.base.hashset") + +-- the stl headers list +function _stl_headers() + return { + "algorithm", + "forward_list", + "numbers", + "stop_token", + "any", + "fstream", + "numeric", + "streambuf", + "array", + "functional", + "optional", + "string", + "atomic", + "future", + "ostream", + "string_view", + "barrier", + "initializer_list", + "queue", + "bit", + "iomanip", + "random", + "syncstream", + "bitset", + "ios", + "ranges", + "system_error", + "charconv", + "iosfwd", + "ratio", + "thread", + "chrono", + "iostream", + "regex", + "tuple", + "codecvt", + "istream", + "scoped_allocator", + "typeindex", + "compare", + "iterator", + "semaphore", + "typeinfo", + "complex", + "latch", + "set", + "type_traits", + "concepts", + "limits", + "shared_mutex", + "unordered_map", + "condition_variable", + "list", + "source_location", + "unordered_set", + "coroutine", + "locale", + "span", + "utility", + "deque", + "map", + "spanstream", + "valarray", + "exception", + "memory", + "sstream", + "variant", + "execution", + "memory_resource", + "stack", + "vector", + "filesystem", + "mutex", + "version", + "format", + "new", + "type_traits", + "string_view", + "stdexcept"} +end + +-- get all stl headers +function get_stl_headers() + local stl_headers = _g.stl_headers + if stl_headers == nil then + stl_headers = hashset.from(_stl_headers()) + _g.stl_headers = stl_headers or false + end + return stl_headers or nil +end + +-- is stl header? +function is_stl_header(header) + return get_stl_headers():has(header) +end + diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index a46947a53..7b6697eeb 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -87,6 +87,7 @@ rule("c++.build.modules.builder") -- patch sourcebatch import("modules_support.common") + import("modules_support.stl_headers") sourcebatch.objectfiles = {} sourcebatch.dependfiles = {} common.patch_sourcebatch(target, sourcebatch, opt) @@ -101,7 +102,7 @@ rule("c++.build.modules.builder") if r.method ~= "by-name" then headerunits = headerunits or {} local unittype = r.method == "include-angle" and ":angle" or ":quote" - table.append(headerunits, {name = name, path = r.path, type = unittype, stl = common.is_stl_header(name)}) + table.append(headerunits, {name = name, path = r.path, type = unittype, stl = stl_headers.is_stl_header(name)}) end end break -- cgit v1.3.1 From 739e62f633aa8307d0c1ab6f33b35d08560a58fe Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:47:15 +0800 Subject: rename some apis --- xmake/rules/c++/modules/modules_support/clang.lua | 16 +++++----- xmake/rules/c++/modules/modules_support/common.lua | 36 ++++++++++------------ xmake/rules/c++/modules/modules_support/gcc.lua | 8 ++--- xmake/rules/c++/modules/modules_support/msvc.lua | 14 ++++----- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 666eb2135..3cb79ac40 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -29,12 +29,12 @@ import("common") -- load parent target with modules files function load_parent(target, opt) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) + cachedir = common.get_modules_cachedir(dep) target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) end end @@ -42,8 +42,8 @@ end -- check C++20 module support function check_module_support(target) local compinst = compiler.load("cxx", {target = target}) - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) + local cachedir = common.get_modules_cachedir(target) + local stlcachedir = common.get_stlmodules_cachedir(target) -- get module and module cache flags local modulesflag = get_modulesflag(target) @@ -87,7 +87,7 @@ function toolchain_include_directories(target) end function generate_dependencies(target, sourcebatch, opt) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) @@ -114,8 +114,8 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) + local cachedir = common.get_modules_cachedir(target) + local stlcachedir = common.get_stlmodules_cachedir(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") @@ -190,7 +190,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index b86ad8f1f..8ef1877f0 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -26,7 +26,8 @@ import("core.tool.compiler") import("core.project.project") import("lib.detect.find_file") -function get_stlcache_dir(target) +-- get stl modules cache directory +function get_stlmodules_cachedir(target) local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") if target:has_tool("cxx", "clang", "clangxx") then stlcachedir = path.join(config.buildir(), "stlmodules", "cache") @@ -34,24 +35,24 @@ function get_stlcache_dir(target) if not os.isdir(stlcachedir) then os.mkdir(stlcachedir) end - return path.translate(stlcachedir) + return stlcachedir end -function get_cache_dir(target) +-- get modules cache directory +function get_modules_cachedir(target) local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") if not os.isdir(cachedir) then os.mkdir(cachedir) end - return path.translate(cachedir) + return cachedir end +-- patch sourcebatch function patch_sourcebatch(target, sourcebatch, opt) - local cachedir = get_cache_dir(target) - + local cachedir = get_modules_cachedir(target) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) @@ -60,17 +61,7 @@ function patch_sourcebatch(target, sourcebatch, opt) end end -function get_bmi_ext(target) - if target:has_tool("cxx", "gcc", "gxx") then - return import("gcc").get_bmi_ext() - elseif target:has_tool("cxx", "cl") then - return import("msvc").get_bmi_ext() - elseif target:has_tool("cxx", "clang", "clangxx") then - return import("clang").get_bmi_ext() - end - assert(false) -end - +-- get modules support function modules_support(target) local module_builder if target:has_tool("cxx", "clang", "clangxx") then @@ -86,6 +77,11 @@ function modules_support(target) return module_builder end +-- get bmi extension +function get_bmi_ext(target) + return modules_support(target).get_bmi_ext() +end + function contains_modules(target) local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false @@ -100,7 +96,7 @@ function contains_modules(target) end function load(target, sourcebatch, opt) - local cachedir = get_cache_dir(target) + local cachedir = get_modules_cachedir(target) local moduleinfos for _, sourcefile in ipairs(sourcebatch.sourcefiles) do @@ -123,7 +119,7 @@ function load(target, sourcebatch, opt) end function parse_dependency_data(target, moduleinfos, opt) - local cachedir = get_cache_dir(target) + local cachedir = get_modules_cachedir(target) local modules for _, moduleinfo in ipairs(moduleinfos) do diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index db29c1bef..1053eb56a 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -99,7 +99,7 @@ end -- generate dependency files function generate_dependencies(target, sourcebatch, opt) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) local compinst = target:compiler("cxx") local common_args = {"-E", "-x", "c++"} @@ -141,8 +141,8 @@ end function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) + local cachedir = common.get_modules_cachedir(target) + local stlcachedir = common.get_stlmodules_cachedir(target) local mapper_file = get_module_mapper() @@ -209,7 +209,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) local compinst = target:compiler("cxx") diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index ca7ca19e7..6f004ee5f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -31,7 +31,7 @@ function load_parent(target, opt) local ifcsearchdirflag = get_ifcsearchdirflag(target) for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) + cachedir = common.get_modules_cachedir(dep) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) end end @@ -39,8 +39,8 @@ end -- check C++20 module support function check_module_support(target) local compinst = target:compiler("cxx") - local cachedir = common.get_cache_dir(target) - local stlcachedir = common.get_stlcache_dir(target) + local cachedir = common.get_modules_cachedir(target) + local stlcachedir = common.get_stlmodules_cachedir(target) -- get flags local modulesflag = get_modulesflag(target) @@ -89,7 +89,7 @@ function generate_dependencies(target, sourcebatch, opt) local scandependenciesflag = get_scandependenciesflag(target) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) local common_args = {"/TP", scandependenciesflag} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do @@ -133,8 +133,8 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) 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) + local cachedir = common.get_modules_cachedir(target) + local stlcachedir = common.get_stlmodules_cachedir(target) -- build headerunits local common_args = {"/TP", exportheaderflag, "/c"} @@ -197,7 +197,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_cache_dir(target) + local cachedir = common.get_modules_cachedir(target) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") -- cgit v1.3.1 From 5e4888e6d5bfe276fa3d69b09e2db2bd52014e9b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:48:54 +0800 Subject: improve contains modules --- xmake/rules/c++/modules/modules_support/clang.lua | 24 ++++----- xmake/rules/c++/modules/modules_support/common.lua | 62 +++++++++++++--------- xmake/rules/c++/modules/modules_support/gcc.lua | 14 ++--- xmake/rules/c++/modules/modules_support/msvc.lua | 22 ++++---- 4 files changed, 67 insertions(+), 55 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 3cb79ac40..e1e136c97 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -29,12 +29,12 @@ import("common") -- load parent target with modules files function load_parent(target, opt) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_modules_cachedir(dep) + cachedir = common.modules_cachedir(dep) target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) end end @@ -42,8 +42,8 @@ end -- check C++20 module support function check_module_support(target) local compinst = compiler.load("cxx", {target = target}) - local cachedir = common.get_modules_cachedir(target) - local stlcachedir = common.get_stlmodules_cachedir(target) + local cachedir = common.modules_cachedir(target) + local stlcachedir = common.stlmodules_cachedir(target) -- get module and module cache flags local modulesflag = get_modulesflag(target) @@ -87,7 +87,7 @@ function toolchain_include_directories(target) end function generate_dependencies(target, sourcebatch, opt) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) @@ -114,8 +114,8 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_modules_cachedir(target) - local stlcachedir = common.get_stlmodules_cachedir(target) + local cachedir = common.modules_cachedir(target) + local stlcachedir = common.stlmodules_cachedir(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") @@ -145,7 +145,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) os.mkdir(outdir) end - local bmifilename = path.basename(objectfile) .. get_bmi_ext() + local bmifilename = path.basename(objectfile) .. bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then @@ -168,7 +168,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.append(public_flags, modulefileflag .. bmifile) else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) if not os.isfile(bmifile) then local args = { modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path } @@ -190,7 +190,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) @@ -246,7 +246,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function get_bmi_ext() +function bmi_extension() return ".pcm" end @@ -345,7 +345,7 @@ function get_modulefileflag(target) local modulefileflag = _g.modulefileflag if modulefileflag == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-fmodule-file=" .. os.tmpfile() .. get_bmi_ext(), "cxxflags", {flagskey = "clang_module_file"}) then + if compinst:has_flags("-fmodule-file=" .. os.tmpfile() .. bmi_extension(), "cxxflags", {flagskey = "clang_module_file"}) then modulefileflag = "-fmodule-file=" end assert(modulefileflag, "compiler(clang): does not support c++ module!") diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 8ef1877f0..a8668f2bf 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -23,11 +23,17 @@ import("core.base.json") import("core.base.hashset") import("core.project.config") import("core.tool.compiler") +import("core.cache.memcache", {alias = "_memcache"}) import("core.project.project") import("lib.detect.find_file") +-- get memcache +function memcache() + return _memcache.cache("rule.cxx.modules") +end + -- get stl modules cache directory -function get_stlmodules_cachedir(target) +function stlmodules_cachedir(target) local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") if target:has_tool("cxx", "clang", "clangxx") then stlcachedir = path.join(config.buildir(), "stlmodules", "cache") @@ -39,7 +45,7 @@ function get_stlmodules_cachedir(target) end -- get modules cache directory -function get_modules_cachedir(target) +function modules_cachedir(target) local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") if not os.isdir(cachedir) then os.mkdir(cachedir) @@ -49,7 +55,7 @@ end -- patch sourcebatch function patch_sourcebatch(target, sourcebatch, opt) - local cachedir = get_modules_cachedir(target) + local cachedir = modules_cachedir(target) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} @@ -63,40 +69,46 @@ end -- get modules support function modules_support(target) - local module_builder - if target:has_tool("cxx", "clang", "clangxx") then - module_builder = import("clang", {anonymous = true}) - elseif target:has_tool("cxx", "gcc", "gxx") then - module_builder = import("gcc", {anonymous = true}) - elseif target:has_tool("cxx", "cl") then - module_builder = import("msvc", {anonymous = true}) - else - local _, toolname = target:tool("cxx") - raise("compiler(%s): does not support c++ module!", toolname) + local cachekey = tostring(target) + local module_builder = memcache():get2("modules_support", cachekey) + if module_builder == nil then + if target:has_tool("cxx", "clang", "clangxx") then + module_builder = import("clang", {anonymous = true}) + elseif target:has_tool("cxx", "gcc", "gxx") then + module_builder = import("gcc", {anonymous = true}) + elseif target:has_tool("cxx", "cl") then + module_builder = import("msvc", {anonymous = true}) + else + local _, toolname = target:tool("cxx") + raise("compiler(%s): does not support c++ module!", toolname) + end + memcache():set2("modules_support", cachekey, module_builder) end return module_builder end -- get bmi extension -function get_bmi_ext(target) - return modules_support(target).get_bmi_ext() +function bmi_extension(target) + return modules_support(target).bmi_extension() end +-- this target contains module files? function contains_modules(target) local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false - - for _, dep in ipairs(target:orderdeps()) do - local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then - target_with_modules = true - break + if not target_with_modules then + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + target_with_modules = true + break + end end end return target_with_modules end function load(target, sourcebatch, opt) - local cachedir = get_modules_cachedir(target) + local cachedir = modules_cachedir(target) local moduleinfos for _, sourcefile in ipairs(sourcebatch.sourcefiles) do @@ -119,7 +131,7 @@ function load(target, sourcebatch, opt) end function parse_dependency_data(target, moduleinfos, opt) - local cachedir = get_modules_cachedir(target) + local cachedir = modules_cachedir(target) local modules for _, moduleinfo in ipairs(moduleinfos) do @@ -140,7 +152,7 @@ function parse_dependency_data(target, moduleinfos, opt) m.provides[provide["logical-name"] ] = path.translate(provide["compiled-module-path"]) end else -- assume path with name - local name = provide["logical-name"] .. get_bmi_ext(target) + local name = provide["logical-name"] .. bmi_extension(target) name:replace(":", "-") m.provides[provide["logical-name"] ] = { @@ -347,7 +359,7 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) end if module_name then - table.append(rule.outputs, module_name .. get_bmi_ext(target)) + table.append(rule.outputs, module_name .. bmi_extension(target)) local provide = {} provide["logical-name"] = module_name diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 1053eb56a..9812115b8 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -99,7 +99,7 @@ end -- generate dependency files function generate_dependencies(target, sourcebatch, opt) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") local common_args = {"-E", "-x", "c++"} @@ -141,8 +141,8 @@ end function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") - local cachedir = common.get_modules_cachedir(target) - local stlcachedir = common.get_stlmodules_cachedir(target) + local cachedir = common.modules_cachedir(target) + local stlcachedir = common.stlmodules_cachedir(target) local mapper_file = get_module_mapper() @@ -165,7 +165,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) os.mkdir(outdir) end - local bmifilename = path.basename(objectfile) .. get_bmi_ext() + local bmifilename = path.basename(objectfile) .. bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then @@ -190,7 +190,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depcache(target:dependfile(bmifile)) end else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then if not os.isfile(bmifile) then @@ -209,7 +209,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") @@ -247,7 +247,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function get_bmi_ext() +function bmi_extension() return ".gcm" end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 6f004ee5f..c7a6f6c15 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -31,7 +31,7 @@ function load_parent(target, opt) local ifcsearchdirflag = get_ifcsearchdirflag(target) for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_modules_cachedir(dep) + cachedir = common.modules_cachedir(dep) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) end end @@ -39,8 +39,8 @@ end -- check C++20 module support function check_module_support(target) local compinst = target:compiler("cxx") - local cachedir = common.get_modules_cachedir(target) - local stlcachedir = common.get_stlmodules_cachedir(target) + local cachedir = common.modules_cachedir(target) + local stlcachedir = common.stlmodules_cachedir(target) -- get flags local modulesflag = get_modulesflag(target) @@ -89,7 +89,7 @@ function generate_dependencies(target, sourcebatch, opt) local scandependenciesflag = get_scandependenciesflag(target) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) local common_args = {"/TP", scandependenciesflag} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do @@ -133,8 +133,8 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - local cachedir = common.get_modules_cachedir(target) - local stlcachedir = common.get_stlmodules_cachedir(target) + local cachedir = common.modules_cachedir(target) + local stlcachedir = common.stlmodules_cachedir(target) -- build headerunits local common_args = {"/TP", exportheaderflag, "/c"} @@ -158,7 +158,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) os.mkdir(outdir) end - local bmifilename = path.basename(objectfile) .. get_bmi_ext() + local bmifilename = path.basename(objectfile) .. bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then @@ -179,7 +179,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.join2(public_flags, flag) target:add("objectfiles", objectfile) else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_ext()) + local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) @@ -187,7 +187,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_ext()} + local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. bmi_extension()} table.join2(private_flags, flag) end end @@ -197,7 +197,7 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.get_modules_cachedir(target) + local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") @@ -253,7 +253,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function get_bmi_ext() +function bmi_extension() return ".ifc" end -- cgit v1.3.1 From e5e255ea8e3516dfd38802b8540ae866f4cef376 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:50:21 +0800 Subject: format some codes --- xmake/rules/c++/modules/modules_support/common.lua | 67 ++++------------------ 1 file changed, 12 insertions(+), 55 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index a8668f2bf..b01327267 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -107,18 +107,15 @@ function contains_modules(target) return target_with_modules end +-- load module infos function load(target, sourcebatch, opt) - local cachedir = modules_cachedir(target) - local moduleinfos for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) if os.isfile(dependfile) then local data = io.load(dependfile) - if data then moduleinfos = moduleinfos or {} - local moduleinfo = json.decode(data.moduleinfo) moduleinfo.sourcefile = sourcefile if moduleinfo then @@ -130,38 +127,34 @@ function load(target, sourcebatch, opt) return moduleinfos end +-- parse module dependency data function parse_dependency_data(target, moduleinfos, opt) - local cachedir = modules_cachedir(target) - local modules + local cachedir = modules_cachedir(target) for _, moduleinfo in ipairs(moduleinfos) do assert(moduleinfo.version <= 1) for _, rule in ipairs(moduleinfo.rules) do modules = modules or {} - local m = {} - for _, provide in ipairs(rule.provides) do m.provides = m.provides or {} - assert(provide["logical-name"]) if provide["compiled-module-path"] then if not path.is_absolute(provide["compiled-module-path"]) then - m.provides[provide["logical-name"] ] = path.absolute(path.translate(provide["compiled-module-path"])) + m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) else - m.provides[provide["logical-name"] ] = path.translate(provide["compiled-module-path"]) + m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) end - else -- assume path with name + else + -- assume path with name local name = provide["logical-name"] .. bmi_extension(target) name:replace(":", "-") - - m.provides[provide["logical-name"] ] = { + m.provides[provide["logical-name"]] = { bmi = path.join(cachedir, name), sourcefile = moduleinfo.sourcefile } end end - assert(rule["primary-output"]) modules[path.translate(rule["primary-output"])] = m end @@ -172,18 +165,16 @@ function parse_dependency_data(target, moduleinfos, opt) local m = modules[path.translate(rule["primary-output"])] for _, r in ipairs(rule.requires) do m.requires = m.requires or {} - local p = r["source-path"] if not p then for _, dependency in pairs(modules) do - if dependency.provides and dependency.provides[r["logical-name"] ] then - p = dependency.provides[r["logical-name"] ].bmi + if dependency.provides and dependency.provides[r["logical-name"]] then + p = dependency.provides[r["logical-name"]].bmi break end end end - - m.requires[r["logical-name"] ] = { + m.requires[r["logical-name"]] = { method = r["lookup-method"] or "by-name", path = p and path.translate(p) or nil, unique = r["unique-on-source-path"] or false @@ -198,18 +189,13 @@ function _topological_sort_visit(node, nodes, modules, output) if node.marked then return end - assert(not node.tempmarked) - node.tempmarked = true - local m1 = modules[node.objectfile] - assert(m1.provides) for _, n in ipairs(nodes) do if not n.tempmarked then local m2 = modules[n.objectfile] - for name, provide in pairs(m1.provides) do if m2.requires and m2.requires[name] then _topological_sort_visit(n, nodes, modules, output) @@ -217,10 +203,8 @@ function _topological_sort_visit(node, nodes, modules, output) end end end - node.tempmarked = false node.marked = true - table.insert(output, 1, node.objectfile) end @@ -230,7 +214,6 @@ function _topological_sort_has_node_without_mark(nodes) return true end end - return false end @@ -244,11 +227,9 @@ end function sort_modules_by_dependencies(objectfiles, modules) local output = {} - local nodes = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m.provides then table.append(nodes, { marked = false, tempmarked = false, objectfile = objectfile }) end @@ -256,7 +237,6 @@ function sort_modules_by_dependencies(objectfiles, modules) while _topological_sort_has_node_without_mark(nodes) do local node = _topological_sort_get_first_unmarked_node(nodes) - _topological_sort_visit(node, nodes, modules, output) end return output @@ -264,29 +244,13 @@ end function find_quote_header_file(target, sourcefile, file) local p = path.join(path.directory(path.absolute(sourcefile, project.directory())), file) - assert(os.isfile(p)) - return p end function find_angle_header_file(target, file) -- check if the header is in subtarget - - local modules_support - if target:has_tool("cxx", "clang", "clangxx") then - modules_support = import("clang") - elseif target:has_tool("cxx", "gcc", "gxx") then - modules_support = import("gcc") - elseif target:has_tool("cxx", "cl") then - modules_support = import("msvc") - else - local _, toolname = target:tool("cxx") - raise("compiler(%s): does not support c++ module!", toolname) - end - - local headerpaths = modules_support.toolchain_include_directories(target) - + local headerpaths = modules_support(target).toolchain_include_directories(target) for _, dep in ipairs(target:orderdeps()) do table.append(headerpaths, dep:scriptdir()) end @@ -301,7 +265,6 @@ function find_angle_header_file(target, file) table.join2(headerpaths, target:get("includedirs")) local p = find_file(file, headerpaths) - assert(p) assert(os.isfile(p)) @@ -333,7 +296,6 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) end local module_depname = line:match("import%s+(.+)%s*;") - if module_depname then local module_dep = {} @@ -351,9 +313,7 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) module_dep["unique-on-source-path"] = true module_dep["source-path"] = find_angle_header_file(target, module_depname) end - module_dep["logical-name"] = module_depname - table.insert(module_deps, module_dep) end end @@ -370,10 +330,7 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) end rule.requires = module_deps - table.append(output.rules, rule) - local jsondata = json.encode(output) - io.writefile(jsonfile, jsondata) end -- cgit v1.3.1 From 038a661150512feededd1e3badb1ad1dab5e30e0 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 00:53:02 +0800 Subject: improve to find angle header file --- xmake/rules/c++/modules/modules_support/common.lua | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index b01327267..57b9c0c7c 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -192,13 +192,15 @@ function _topological_sort_visit(node, nodes, modules, output) assert(not node.tempmarked) node.tempmarked = true local m1 = modules[node.objectfile] - assert(m1.provides) + assert(m1 and m1.provides) for _, n in ipairs(nodes) do if not n.tempmarked then local m2 = modules[n.objectfile] - for name, provide in pairs(m1.provides) do - if m2.requires and m2.requires[name] then - _topological_sort_visit(n, nodes, modules, output) + if m2 then + for name, provide in pairs(m1.provides) do + if m2.requires and m2.requires[name] then + _topological_sort_visit(n, nodes, modules, output) + end end end end @@ -230,8 +232,8 @@ function sort_modules_by_dependencies(objectfiles, modules) local nodes = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m.provides then - table.append(nodes, { marked = false, tempmarked = false, objectfile = objectfile }) + if m and m.provides then + table.append(nodes, {marked = false, tempmarked = false, objectfile = objectfile}) end end @@ -255,13 +257,12 @@ function find_angle_header_file(target, file) table.append(headerpaths, dep:scriptdir()) end - if project.required_packages then - for _, name in ipairs(target:get("packages")) do - local package = project.required_package(name) - table.join2(headerpaths, package:get("sysincludedirs")) + for _, pkg in ipairs(target:pkgs()) do + local includedirs = pkg:get("sysincludedirs") or pkg:get("includedirs") + if includedirs then + table.join2(headerpaths, includedirs) end end - table.join2(headerpaths, target:get("includedirs")) local p = find_file(file, headerpaths) -- cgit v1.3.1 From cc8ee163098a464937769641377fd98c33bdfca2 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:35:52 +0800 Subject: add more tests --- tests/projects/c++/modules/cpp_with_moduledeps/src/main.cpp | 8 ++++++++ tests/projects/c++/modules/cpp_with_moduledeps/src/mod.cpp | 4 ++++ tests/projects/c++/modules/cpp_with_moduledeps/src/mod.mpp | 2 ++ tests/projects/c++/modules/cpp_with_moduledeps/xmake.lua | 10 ++++++++++ 4 files changed, 24 insertions(+) create mode 100644 tests/projects/c++/modules/cpp_with_moduledeps/src/main.cpp create mode 100644 tests/projects/c++/modules/cpp_with_moduledeps/src/mod.cpp create mode 100644 tests/projects/c++/modules/cpp_with_moduledeps/src/mod.mpp create mode 100644 tests/projects/c++/modules/cpp_with_moduledeps/xmake.lua diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/src/main.cpp b/tests/projects/c++/modules/cpp_with_moduledeps/src/main.cpp new file mode 100644 index 000000000..b943e786a --- /dev/null +++ b/tests/projects/c++/modules/cpp_with_moduledeps/src/main.cpp @@ -0,0 +1,8 @@ +// main.cpp +import mod; + +int main() +{ + f(); + return 0; +} diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.cpp b/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.cpp new file mode 100644 index 000000000..bedf48a6c --- /dev/null +++ b/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.cpp @@ -0,0 +1,4 @@ +module mod; +void f() +{ +} diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.mpp b/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.mpp new file mode 100644 index 000000000..0f77aa62b --- /dev/null +++ b/tests/projects/c++/modules/cpp_with_moduledeps/src/mod.mpp @@ -0,0 +1,2 @@ +export module mod; +export void f(); diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/xmake.lua b/tests/projects/c++/modules/cpp_with_moduledeps/xmake.lua new file mode 100644 index 000000000..5c7a8a6f7 --- /dev/null +++ b/tests/projects/c++/modules/cpp_with_moduledeps/xmake.lua @@ -0,0 +1,10 @@ +set_languages("c++20") + +target("mod") + set_kind("static") + add_files("src/mod.mpp", "src/mod.cpp") + +target("main") + set_kind("binary") + add_deps("mod") + add_files("src/main.cpp") -- cgit v1.3.1 From 0e52b4967cd20677c1dcc7656e2016c076ed2647 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:37:59 +0800 Subject: improve load modules --- xmake/rules/c++/modules/modules_support/clang.lua | 24 ++++++++-------------- xmake/rules/c++/modules/modules_support/common.lua | 2 +- xmake/rules/c++/modules/modules_support/gcc.lua | 8 ++------ xmake/rules/c++/modules/modules_support/msvc.lua | 24 ++++++++++------------ xmake/rules/c++/modules/xmake.lua | 9 +++----- 5 files changed, 26 insertions(+), 41 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index e1e136c97..04ea0ab6e 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -27,20 +27,8 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") --- load parent target with modules files -function load_parent(target, opt) - local cachedir = common.modules_cachedir(target) - - local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) - - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.modules_cachedir(dep) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) - end -end - --- check C++20 module support -function check_module_support(target) +-- load module support for the current target +function load(target) local compinst = compiler.load("cxx", {target = target}) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -57,8 +45,14 @@ function check_module_support(target) -- add the module cache directory target:add("cxxflags", implicitmodulesflag, {force = true}) target:add("cxxflags", implicitmodulemapsflag, {force = true}) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + + -- add module cachedirs of all dependent targets with modules + -- this target maybe does not contain module files + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.modules_cachedir(dep) + target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) + end end function toolchain_include_directories(target) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 57b9c0c7c..ae3de7493 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -108,7 +108,7 @@ function contains_modules(target) end -- load module infos -function load(target, sourcebatch, opt) +function load_moduleinfos(target, sourcebatch, opt) local moduleinfos for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 9812115b8..fc346d753 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -52,12 +52,8 @@ function add_module_to_mapper(file, module, bmi) return true end --- load parent target with modules files -function load_parent(target, opt) -end - --- check C++20 module support -function check_module_support(target) +-- load module support for the current target +function load(target) local compinst = compiler.load("cxx", {target = target}) local modulesflag = get_modulesflag(target) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index c7a6f6c15..98d244626 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -14,7 +14,7 @@ -- -- Copyright (C) 2015-present, TBOOX Open Source Group. -- --- @author ruki +-- @author ruki, Arthapz -- @file msvc.lua -- @@ -26,18 +26,8 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") --- load parent target with modules files -function load_parent(target, opt) - local ifcsearchdirflag = get_ifcsearchdirflag(target) - - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.modules_cachedir(dep) - target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) - end -end - --- check C++20 module support -function check_module_support(target) +-- load module support for the current target +function load(target) local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -65,6 +55,14 @@ function check_module_support(target) break end end + + -- add module cachedirs of all dependent targets with modules + -- this target maybe does not contain module files + local ifcsearchdirflag = get_ifcsearchdirflag(target) + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.modules_cachedir(dep) + target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) + end end -- provide toolchain include dir for stl headerunit when p1689 is not supported diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 7b6697eeb..9a7599358 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -41,14 +41,11 @@ rule("c++.build.modules") -- get modules support local modules_support = common.modules_support(target) - -- check C++20 module support - modules_support.check_module_support(target) + -- load module support + modules_support.load(target) -- mark this target with modules target:data_set("cxx.has_modules", true) - - -- load parent - modules_support.load_parent(target, opt) end end) @@ -69,7 +66,7 @@ rule("c++.build.modules.dependencies") modules_support.generate_dependencies(target, sourcebatch, opt) -- load and parse module dependencies - local moduleinfos = common.load(target, sourcebatch, opt) + local moduleinfos = common.load_moduleinfos(target, sourcebatch, opt) local modules = common.parse_dependency_data(target, moduleinfos, opt) target:data_set("cxx.modules", modules) end) -- cgit v1.3.1 From 4e95000424f80810f2a7af5444a1a07c712057ff Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:41:24 +0800 Subject: improve modules for msvc --- xmake/rules/c++/modules/modules_support/clang.lua | 4 +- xmake/rules/c++/modules/modules_support/common.lua | 2 +- xmake/rules/c++/modules/modules_support/gcc.lua | 2 +- xmake/rules/c++/modules/modules_support/msvc.lua | 67 ++++++++-------------- 4 files changed, 29 insertions(+), 46 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 04ea0ab6e..b2425db71 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -48,7 +48,7 @@ function load(target) target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) -- add module cachedirs of all dependent targets with modules - -- this target maybe does not contain module files + -- this target maybe does not contain module files, @see https://github.com/xmake-io/xmake/issues/1858 for _, dep in ipairs(target:orderdeps()) do cachedir = common.modules_cachedir(dep) target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) @@ -240,7 +240,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function bmi_extension() +function get_bmi_extension() return ".pcm" end diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index ae3de7493..95ddeb65f 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -89,7 +89,7 @@ end -- get bmi extension function bmi_extension(target) - return modules_support(target).bmi_extension() + return modules_support(target).get_bmi_extension() end -- this target contains module files? diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index fc346d753..e10bb0433 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -243,7 +243,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function bmi_extension() +function get_bmi_extension() return ".gcm" end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 98d244626..fdaa27017 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -57,7 +57,7 @@ function load(target) end -- add module cachedirs of all dependent targets with modules - -- this target maybe does not contain module files + -- this target maybe does not contain module files, @see https://github.com/xmake-io/xmake/issues/1858 local ifcsearchdirflag = get_ifcsearchdirflag(target) for _, dep in ipairs(target:orderdeps()) do cachedir = common.modules_cachedir(dep) @@ -76,7 +76,7 @@ function toolchain_include_directories(target) break end end - assert(false) + raise("msvc toolchain includedirs not found!") end -- generate dependency files @@ -84,34 +84,27 @@ function generate_dependencies(target, sourcebatch, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - local scandependenciesflag = get_scandependenciesflag(target) - - local cachedir = common.modules_cachedir(target) local common_args = {"/TP", scandependenciesflag} - + local cachedir = common.modules_cachedir(target) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) 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()))) - if not os.isdir(outdir) then - os.mkdir(outdir) + local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir()))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end - local jsonfile = path.join(outdir, path.filename(sourcefile) .. ".json") - + local jsonfile = path.join(outputdir, path.filename(sourcefile) .. ".json") if scandependenciesflag then local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end local dependinfo = io.readfile(jsonfile) - return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end @@ -128,9 +121,9 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) 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!") + -- get cachedirs local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -142,28 +135,24 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) for _, headerunit in ipairs(sourcebatch) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) - - local outdir + local outputdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) else - outdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) + outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) end - - if not os.isdir(outdir) then - os.mkdir(outdir) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end local bmifilename = path.basename(objectfile) .. bmi_extension() - - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end - local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outdir, "/Fo" .. objectfile} + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) @@ -189,7 +178,6 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.join2(private_flags, flag) end end - return public_flags, private_flags end @@ -215,14 +203,12 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local common_args = {"/TP"} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end local args = {"/c", "/Fo" .. objectfile} - local flag = {} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -251,7 +237,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end -function bmi_extension() +function get_bmi_extension() return ".ifc" end @@ -265,7 +251,7 @@ function get_modulesflag(target) assert(modulesflag, "compiler(msvc): does not support c++ module!") _g.modulesflag = modulesflag or false end - return modulesflag + return modulesflag or nil end function get_ifcoutputflag(target) @@ -278,7 +264,7 @@ function get_ifcoutputflag(target) assert(ifcoutputflag, "compiler(msvc): does not support c++ module!") _g.ifcoutputflag = ifcoutputflag or false end - return ifcoutputflag + return ifcoutputflag or nil end function get_ifcsearchdirflag(target) @@ -291,7 +277,7 @@ function get_ifcsearchdirflag(target) assert(ifcsearchdirflag, "compiler(msvc): does not support c++ module!") _g.ifcsearchdirflag = ifcsearchdirflag or false end - return ifcsearchdirflag + return ifcsearchdirflag or nil end function get_interfaceflag(target) @@ -317,7 +303,7 @@ function get_referenceflag(target) assert(referenceflag, "compiler(msvc): does not support c++ module!") _g.referenceflag = referenceflag or false end - return referenceflag + return referenceflag or nil end function get_headernameflag(target) @@ -330,7 +316,7 @@ function get_headernameflag(target) end _g.headernameflag = headernameflag or false end - return headernameflag + return headernameflag or nil end function get_headerunitflag(target) @@ -343,12 +329,11 @@ function get_headerunitflag(target) end _g.headerunitflag = headerunitflag or false end - return headerunitflag + return headerunitflag or nil end function get_exportheaderflag(target) local modulesflag = get_modulesflag(target) - local exportheaderflag = _g.exportheaderflag if exportheaderflag == nil then local compinst = target:compiler("cxx") @@ -357,7 +342,7 @@ function get_exportheaderflag(target) end _g.exportheaderflag = exportheaderflag or false end - return exportheaderflag + return exportheaderflag or nil end function get_stdifcdirflag(target) @@ -369,7 +354,7 @@ function get_stdifcdirflag(target) end _g.stdifcdirflag = stdifcdirflag or false end - return stdifcdirflag + return stdifcdirflag or nil end function get_scandependenciesflag(target) @@ -382,16 +367,14 @@ function get_scandependenciesflag(target) 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 + return scandependenciesflag or nil end -- cgit v1.3.1 From 78a52f5c6238dd163e90c2b8bb6f1fc82b0a86a7 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:44:24 +0800 Subject: fix module flags for msvc/clang --- xmake/rules/c++/modules/modules_support/clang.lua | 79 ++++++++--------------- xmake/rules/c++/modules/modules_support/gcc.lua | 6 +- xmake/rules/c++/modules/modules_support/msvc.lua | 15 ++--- 3 files changed, 37 insertions(+), 63 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index b2425db71..6fc0e340a 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -29,7 +29,6 @@ import("common") -- load module support for the current target function load(target) - local compinst = compiler.load("cxx", {target = target}) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -55,15 +54,14 @@ function load(target) end end +-- provide toolchain include dir for stl headerunit when p1689 is not supported function toolchain_include_directories(target) local includedirs = _g.includedirs if includedirs == nil then includedirs = {} - - local gcc, toolname = target:tool("cc") - assert(toolname, "clang") - - local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + local clang, toolname = target:tool("cc") + assert(toolname == "clang") + local _, result = try {function () return os.iorunv(clang, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() @@ -75,14 +73,14 @@ function toolchain_include_directories(target) end end end - _g.includedirs = includedirs or {} + _g.includedirs = includedirs end return includedirs end +-- generate dependency files function generate_dependencies(target, sourcebatch, opt) local cachedir = common.modules_cachedir(target) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() @@ -93,13 +91,11 @@ function generate_dependencies(target, sourcebatch, opt) os.mkdir(outdir) end - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) - -- no support of p1689 atm + local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) common.fallback_generate_dependencies(target, jsonfile, sourcefile) local dependinfo = io.readfile(jsonfile) - return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end @@ -110,7 +106,6 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) - assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- get headerunits flags @@ -125,7 +120,6 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) for _, headerunit in ipairs(sourcebatch) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) local outdir @@ -134,23 +128,21 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) else outdir = path.join(cachedir, path.directory(headerunit.path)) end - if not os.isdir(outdir) then os.mkdir(outdir) end - local bmifilename = path.basename(objectfile) .. bmi_extension() - + local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end - local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile } + local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} if headerunit.type == ":quote" then - table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path }) + table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) elseif headerunit.type == ":angle" then - table.join2(args, { "-x", "c++-system-header", headerunit.name }) + table.join2(args, {"-x", "c++-system-header", headerunit.name}) end batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -162,14 +154,11 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.append(public_flags, modulefileflag .. bmifile) else - local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) - + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then - local args = { modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path } - + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - end batchcmds:set_depmtime(os.mtime(bmifile)) @@ -199,17 +188,16 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) flags = table.unique(flags) target:add("cxxflags", flags, {force = true, expand = false}) - local common_args = { modulecachepathflag .. cachedir } + local common_args = {modulecachepathflag .. cachedir} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end local args = { emitmoduleinterfaceflag } - local flag = {} + local bmiflags = {} local bmifiles = {} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -222,7 +210,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - table.join2(flag, { modulefileflag .. bmifile }) + table.join2(bmiflags, {modulefileflag .. bmifile}) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) @@ -231,9 +219,9 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(objectfile)) batchcmds:set_depcache(target:dependfile(objectfile)) - target:add("cxxflags", flag, {public = true, force = true}) + target:add("cxxflags", bmiflags, {public = true, force = true}) target:add("objectfiles", objectfile) - for _, f in ipairs(flag) do + for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) end end @@ -251,18 +239,15 @@ function get_modulesflag(target) if compinst:has_flags("-fmodules", "cxxflags", {flagskey = "clang_modules"}) then modulesflag = "-fmodules" end - if not modulesflag then if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "clang_modules_ts"}) then modulesflag = "-fmodules-ts" end end - assert(modulesflag, "compiler(clang): does not support c++ module!") - _g.modulesflag = modulesflag or false end - return modulesflag + return modulesflag or nil end function get_implicitmodulesflag(target) @@ -273,10 +258,9 @@ function get_implicitmodulesflag(target) implicitmodulesflag = "-fimplicit-modules" end assert(implicitmodulesflag, "compiler(clang): does not support c++ module!") - _g.implicitmodulesflag = implicitmodulesflag or false end - return implicitmodulesflag + return implicitmodulesflag or nil end function get_implicitmodulemapsflag(target) @@ -287,10 +271,9 @@ function get_implicitmodulemapsflag(target) implicitmodulemapsflag = "-fimplicit-module-maps" end assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") - _g.implicitmodulemapsflag = implicitmodulemapsflag or false end - return implicitmodulemapsflag + return implicitmodulemapsflag or nil end function get_prebuiltmodulepathflag(target) @@ -301,10 +284,9 @@ function get_prebuiltmodulepathflag(target) prebuiltmodulepathflag = "-fprebuilt-module-path=" end assert(prebuiltmodulepathflag, "compiler(clang): does not support c++ module!") - _g.prebuiltmodulepathflag = prebuiltmodulepathflag or false end - return prebuiltmodulepathflag + return prebuiltmodulepathflag or nil end function get_modulecachepathflag(target) @@ -315,10 +297,9 @@ function get_modulecachepathflag(target) modulecachepathflag = "-fmodules-cache-path=" end assert(modulecachepathflag, "compiler(clang): does not support c++ module!") - _g.modulecachepathflag = modulecachepathflag or false end - return modulecachepathflag + return modulecachepathflag or nil end function get_emitmoduleflag(target) @@ -329,24 +310,22 @@ function get_emitmoduleflag(target) emitmoduleflag = " -emit-module" end assert(emitmoduleflag, "compiler(clang): does not support c++ module!") - _g.emitmoduleflag = emitmoduleflag or false end - return emitmoduleflag + return emitmoduleflag or nil end function get_modulefileflag(target) local modulefileflag = _g.modulefileflag if modulefileflag == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-fmodule-file=" .. os.tmpfile() .. bmi_extension(), "cxxflags", {flagskey = "clang_module_file"}) then + if compinst:has_flags("-fmodule-file=" .. os.tmpfile() .. get_bmi_extension(), "cxxflags", {flagskey = "clang_module_file"}) then modulefileflag = "-fmodule-file=" end assert(modulefileflag, "compiler(clang): does not support c++ module!") - _g.modulefileflag = modulefileflag or false end - return modulefileflag + return modulefileflag or nil end function get_emitmoduleinterfaceflag(target) @@ -357,10 +336,9 @@ function get_emitmoduleinterfaceflag(target) emitmoduleinterfaceflag = "-emit-module-interface" end assert(emitmoduleinterfaceflag, "compiler(clang): does not support c++ module!") - _g.emitmoduleinterfaceflag = emitmoduleinterfaceflag or false end - return emitmoduleinterfaceflag + return emitmoduleinterfaceflag or nil end function has_headerunitsupport(target) @@ -371,8 +349,7 @@ function has_headerunitsupport(target) compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support"}) then support_headerunits = true end - _g.support_headerunits = support_headerunits or false end - return support_headerunits + return support_headerunits or nil end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e10bb0433..74e2a708e 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -54,8 +54,6 @@ end -- load module support for the current target function load(target) - local compinst = compiler.load("cxx", {target = target}) - local modulesflag = get_modulesflag(target) local modulemapperflag = get_modulemapperflag(target) @@ -161,7 +159,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) os.mkdir(outdir) end - local bmifilename = path.basename(objectfile) .. bmi_extension() + local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then @@ -186,7 +184,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depcache(target:dependfile(bmifile)) end else - local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then if not os.isfile(bmifile) then diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index fdaa27017..37428de7f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -28,7 +28,6 @@ import("common") -- load module support for the current target function load(target) - local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -146,7 +145,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) os.mkdir(outputdir) end - local bmifilename = path.basename(objectfile) .. bmi_extension() + local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) @@ -166,7 +165,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) table.join2(public_flags, flag) target:add("objectfiles", objectfile) else - local bmifile = path.join(stlcachedir, headerunit.name .. bmi_extension()) + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) @@ -174,7 +173,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. bmi_extension()} + local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} table.join2(private_flags, flag) end end @@ -209,7 +208,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end local args = {"/c", "/Fo" .. objectfile} - local flag = {} + local bmiflags = {} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -220,7 +219,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - flag = {referenceflag, name .. "=" .. path.filename(bmifile)} + table.join2(bmiflags, {referenceflag, name .. "=" .. path.filename(bmifile)}) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args, bmi_args), {envs = vcvars}) @@ -228,8 +227,8 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(objectfile)) batchcmds:set_depcache(target:dependfile(objectfile)) - target:add("cxxflags", flag, {force = true, expand = false}) - for _, f in ipairs(flag) do + target:add("cxxflags", bmiflags, {force = true, expand = false}) + for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) end target:add("objectfiles", objectfile) -- cgit v1.3.1 From fd44ddb961977eeed2b15637562da80174f1a5ee Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:46:09 +0800 Subject: format code for gcc --- xmake/rules/c++/modules/modules_support/clang.lua | 6 +-- xmake/rules/c++/modules/modules_support/gcc.lua | 65 ++++++++--------------- 2 files changed, 25 insertions(+), 46 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 6fc0e340a..44150ab21 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -66,7 +66,7 @@ function toolchain_include_directories(target) for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then - table.append(includedirs, line) + table.insert(includedirs, line) break elseif line:startswith("End") then break @@ -152,7 +152,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - table.append(public_flags, modulefileflag .. bmifile) + table.insert(public_flags, modulefileflag .. bmifile) else local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then @@ -164,7 +164,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - table.append(private_flags, modulefileflag .. bmifile) + table.insert(private_flags, modulefileflag .. bmifile) end end return public_flags, private_flags diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 74e2a708e..d3a307d1d 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -28,27 +28,24 @@ import("private.action.build.object", {alias = "objectbuilder"}) import("common") -- get and create the path of module mapper -function get_module_mapper() +function _get_module_mapper() local mapper_file = path.join(config.buildir(), "mapper.txt") if not os.isfile(mapper_file) then io.writefile(mapper_file, "") end - return mapper_file end -- add a module or header unit into the mapper -function add_module_to_mapper(file, module, bmi) +function _add_module_to_mapper(file, module, bmi) for line in io.lines(file) do if line:startswith(module .. " ") then return false end end - local f = io.open(file, "a") f:print("%s %s", module, bmi) f:close() - return true end @@ -56,13 +53,11 @@ end function load(target) local modulesflag = get_modulesflag(target) local modulemapperflag = get_modulemapperflag(target) - target:add("cxxflags", modulesflag) - - if os.isfile(get_module_mapper()) then - os.rm(get_module_mapper()) + if os.isfile(_get_module_mapper()) then + os.rm(_get_module_mapper()) end - target:add("cxxflags", modulemapperflag .. get_module_mapper(), {force = true, expand = false}) + target:add("cxxflags", modulemapperflag .. _get_module_mapper(), {force = true, expand = false}) end -- provide toolchain include dir for stl headerunit when p1689 is not supported @@ -70,23 +65,21 @@ function toolchain_include_directories(target) local includedirs = _g.includedirs if includedirs == nil then includedirs = {} - local gcc, toolname = target:tool("cc") assert(toolname == "gcc") - local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then - table.append(includedirs, line) + table.insert(includedirs, line) break elseif line:startswith("End") then break end end end - _g.includedirs = includedirs or {} + _g.includedirs = includedirs end return includedirs end @@ -100,7 +93,6 @@ function generate_dependencies(target, sourcebatch, opt) local trtbdflag = get_trtbdflag(target) local depfileflag = get_depfileflag(target) local depoutputflag = get_depoutputflag(target) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() @@ -112,20 +104,16 @@ function generate_dependencies(target, sourcebatch, opt) end local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) - if trtbdflag and depfileflag and depoutputflag then local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) - local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, depfileflag .. jsonfile, trtbdflag, depoutputfile .. target:objectfile(sourcefile), "-o", ifile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end local dependinfo = io.readfile(jsonfile) - return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end @@ -134,18 +122,15 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) local compinst = target:compiler("cxx") - local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) - - local mapper_file = get_module_mapper() + local mapper_file = _get_module_mapper() -- build headerunits local objectfiles = {} for _, headerunit in ipairs(sourcebatch) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) local outdir @@ -154,26 +139,24 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) else outdir = path.join(cachedir, path.directory(headerunit.path)) end - if not os.isdir(outdir) then os.mkdir(outdir) end local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end - if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then local args = { "-c" } if headerunit.type == ":quote" then table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) - add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) + _add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) elseif headerunit.type == ":angle" then table.join2(args, { "-x", "c++-system-header", headerunit.name }) - add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) + _add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) end batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -185,8 +168,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) end else local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - - if add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then if not os.isfile(bmifile) then local args = { "-c", "-x", "c++-system-header", headerunit.name } @@ -204,26 +186,23 @@ end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local cachedir = common.modules_cachedir(target) - local compinst = target:compiler("cxx") - - local mapper_file = get_module_mapper() - local common_args = { "-x", "c++" } + local mapper_file = _get_module_mapper() + local common_args = {"-x", "c++"} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then if not os.isdir(path.directory(objectfile)) then os.mkdir(path.directory(objectfile)) end - local args = { "-o", objectfile } + local args = {"-o", objectfile} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) local bmifile = provide.bmi - if add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then - table.join2(args, { "-c", provide.sourcefile }) + if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then + table.join2(args, {"-c", provide.sourcefile}) batchcmds:add_depfiles(provide.sourcefile) batchcmds:set_depmtime(os.mtime(bmifile)) @@ -255,7 +234,7 @@ function get_modulesflag(target) assert(modulesflag, "compiler(gcc): does not support c++ module!") _g.modulesflag = modulesflag or false end - return modulesflag + return modulesflag or nil end function get_modulemapperflag(target) @@ -268,7 +247,7 @@ function get_modulemapperflag(target) assert(modulemapperflag, "compiler(gcc): does not support c++ module!") _g.modulemapperflag = modulemapperflag or false end - return modulemapperflag + return modulemapperflag or nil end function get_trtbdflag(target) @@ -280,7 +259,7 @@ function get_trtbdflag(target) end _g.trtbdflag = trtbdflag or false end - return trtbdflag + return trtbdflag or nil end function get_depfileflag(target) @@ -292,7 +271,7 @@ function get_depfileflag(target) end _g.depfileflag = depfileflag or false end - return depfileflag + return depfileflag or nil end function get_depoutputflag(target) @@ -304,5 +283,5 @@ function get_depoutputflag(target) end _g.depoutputflag = depoutputflag or false end - return depoutputflag + return depoutputflag or nil end -- cgit v1.3.1 From 312dccfb5ffae68ba471d9ebca5569589bb46988 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:53:32 +0800 Subject: improve to get toolchain includedirs --- xmake/rules/c++/modules/modules_support/clang.lua | 32 +++++++++++++++++++-- xmake/rules/c++/modules/modules_support/common.lua | 21 ++++++-------- xmake/rules/c++/modules/modules_support/gcc.lua | 33 +++++++++++++++++++--- xmake/rules/c++/modules/modules_support/msvc.lua | 2 +- 4 files changed, 67 insertions(+), 21 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 44150ab21..865b20a75 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -54,20 +54,46 @@ function load(target) end end --- provide toolchain include dir for stl headerunit when p1689 is not supported -function toolchain_include_directories(target) +-- get includedirs for stl headers +-- +-- $ echo '#include ' | clang -x c++ -E - | grep '/vector"' +-- # 1 "/usr/include/c++/11/vector" 1 3 +-- # 58 "/usr/include/c++/11/vector" 3 +-- # 59 "/usr/include/c++/11/vector" 3 +-- +function _get_toolchain_includedirs_for_stlheaders(includedirs, clang) + local tmpfile = os.tmpfile() .. ".cc" + io.writefile(tmpfile, "#include ") + local result = try {function () return os.iorunv(clang, {"-E", "-x", "c++", tmpfile}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if line:startswith("#") and line:find("/vector\"", 1, true) then + local includedir = line:match("\"(.+)/vector\"") + if includedir and os.isdir(includedir) then + table.insert(includedirs, includedir) + break + end + end + end + end + os.tryrm(tmpfile) +end + +-- provide toolchain include directories for stl headerunit when p1689 is not supported +function toolchain_includedirs(target) local includedirs = _g.includedirs if includedirs == nil then includedirs = {} local clang, toolname = target:tool("cc") assert(toolname == "clang") + _get_toolchain_includedirs_for_stlheaders(includedirs, clang) local _, result = try {function () return os.iorunv(clang, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then table.insert(includedirs, line) - break elseif line:startswith("End") then break end diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 95ddeb65f..7f6f7aa43 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -119,7 +119,7 @@ function load_moduleinfos(target, sourcebatch, opt) local moduleinfo = json.decode(data.moduleinfo) moduleinfo.sourcefile = sourcefile if moduleinfo then - table.append(moduleinfos, moduleinfo) + table.insert(moduleinfos, moduleinfo) end end end @@ -233,7 +233,7 @@ function sort_modules_by_dependencies(objectfiles, modules) for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then - table.append(nodes, {marked = false, tempmarked = false, objectfile = objectfile}) + table.insert(nodes, {marked = false, tempmarked = false, objectfile = objectfile}) end end @@ -251,12 +251,10 @@ function find_quote_header_file(target, sourcefile, file) end function find_angle_header_file(target, file) - -- check if the header is in subtarget - local headerpaths = modules_support(target).toolchain_include_directories(target) + local headerpaths = modules_support(target).toolchain_includedirs(target) for _, dep in ipairs(target:orderdeps()) do - table.append(headerpaths, dep:scriptdir()) + table.insert(headerpaths, dep:scriptdir()) end - for _, pkg in ipairs(target:pkgs()) do local includedirs = pkg:get("sysincludedirs") or pkg:get("includedirs") if includedirs then @@ -264,11 +262,8 @@ function find_angle_header_file(target, file) end end table.join2(headerpaths, target:get("includedirs")) - local p = find_file(file, headerpaths) - assert(p) - assert(os.isfile(p)) - + assert(p, "find <%s> not found!", file) return p end @@ -320,18 +315,18 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) end if module_name then - table.append(rule.outputs, module_name .. bmi_extension(target)) + table.insert(rule.outputs, module_name .. bmi_extension(target)) local provide = {} provide["logical-name"] = module_name provide["source-path"] = path.absolute(sourcefile, project.directory()) rule.provides = {} - table.append(rule.provides, provide) + table.insert(rule.provides, provide) end rule.requires = module_deps - table.append(output.rules, rule) + table.insert(output.rules, rule) local jsondata = json.encode(output) io.writefile(jsonfile, jsondata) end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index d3a307d1d..100f1e2e6 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -60,20 +60,46 @@ function load(target) target:add("cxxflags", modulemapperflag .. _get_module_mapper(), {force = true, expand = false}) end --- provide toolchain include dir for stl headerunit when p1689 is not supported -function toolchain_include_directories(target) +-- get includedirs for stl headers +-- +-- $ echo '#include ' | gcc -x c++ -E - | grep '/vector"' +-- # 1 "/usr/include/c++/11/vector" 1 3 +-- # 58 "/usr/include/c++/11/vector" 3 +-- # 59 "/usr/include/c++/11/vector" 3 +-- +function _get_toolchain_includedirs_for_stlheaders(includedirs, gcc) + local tmpfile = os.tmpfile() .. ".cc" + io.writefile(tmpfile, "#include ") + local result = try {function () return os.iorunv(gcc, {"-E", "-x", "c++", tmpfile}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if line:startswith("#") and line:find("/vector\"", 1, true) then + local includedir = line:match("\"(.+)/vector\"") + if includedir and os.isdir(includedir) then + table.insert(includedirs, includedir) + break + end + end + end + end + os.tryrm(tmpfile) +end + +-- provide toolchain include directories for stl headerunit when p1689 is not supported +function toolchain_includedirs(target) local includedirs = _g.includedirs if includedirs == nil then includedirs = {} local gcc, toolname = target:tool("cc") assert(toolname == "gcc") + _get_toolchain_includedirs_for_stlheaders(includedirs, gcc) local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then table.insert(includedirs, line) - break elseif line:startswith("End") then break end @@ -89,7 +115,6 @@ function generate_dependencies(target, sourcebatch, opt) local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") local common_args = {"-E", "-x", "c++"} - local trtbdflag = get_trtbdflag(target) local depfileflag = get_depfileflag(target) local depoutputflag = get_depoutputflag(target) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 37428de7f..63e445df9 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -65,7 +65,7 @@ function load(target) end -- provide toolchain include dir for stl headerunit when p1689 is not supported -function toolchain_include_directories(target) +function toolchain_includedirs(target) for _, toolchain_inst in ipairs(target:toolchains()) do if toolchain_inst:name() == "msvc" then local vcvars = toolchain_inst:config("vcvars") -- cgit v1.3.1 From 18d9a291ea2988fcef98d754b11824f2567c1020 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:54:02 +0800 Subject: normalize path --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- xmake/rules/c++/modules/modules_support/gcc.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 865b20a75..ae6eaf3cc 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -71,7 +71,7 @@ function _get_toolchain_includedirs_for_stlheaders(includedirs, clang) if line:startswith("#") and line:find("/vector\"", 1, true) then local includedir = line:match("\"(.+)/vector\"") if includedir and os.isdir(includedir) then - table.insert(includedirs, includedir) + table.insert(includedirs, path.normalize(includedir)) break end end @@ -93,7 +93,7 @@ function toolchain_includedirs(target) for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then - table.insert(includedirs, line) + table.insert(includedirs, path.normalize(line)) elseif line:startswith("End") then break end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 100f1e2e6..c270adcf9 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -77,7 +77,7 @@ function _get_toolchain_includedirs_for_stlheaders(includedirs, gcc) if line:startswith("#") and line:find("/vector\"", 1, true) then local includedir = line:match("\"(.+)/vector\"") if includedir and os.isdir(includedir) then - table.insert(includedirs, includedir) + table.insert(includedirs, path.normalize(includedir)) break end end @@ -99,7 +99,7 @@ function toolchain_includedirs(target) for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() if os.isdir(line) then - table.insert(includedirs, line) + table.insert(includedirs, path.normalize(line)) elseif line:startswith("End") then break end -- cgit v1.3.1 From 339c50ca90f0f4fac4c8f3083386eb770f18f06a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:57:08 +0800 Subject: fix typo --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index ae6eaf3cc..0095444ed 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -333,7 +333,7 @@ function get_emitmoduleflag(target) if emitmoduleflag == nil then local compinst = target:compiler("cxx") if compinst:has_flags("-emit-module", "cxxflags", {flagskey = "clang_emit_module"}) then - emitmoduleflag = " -emit-module" + emitmoduleflag = "-emit-module" end assert(emitmoduleflag, "compiler(clang): does not support c++ module!") _g.emitmoduleflag = emitmoduleflag or false -- cgit v1.3.1 From 86dc716cbc9bf052012383f4448a069aa2a0bcb8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Aug 2022 22:57:53 +0800 Subject: improve has_flags --- xmake/modules/detect/tools/cl/has_flags.lua | 3 ++- xmake/modules/detect/tools/gcc/has_flags.lua | 3 ++- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/xmake/modules/detect/tools/cl/has_flags.lua b/xmake/modules/detect/tools/cl/has_flags.lua index ceb3561d4..fe57e38b0 100644 --- a/xmake/modules/detect/tools/cl/has_flags.lua +++ b/xmake/modules/detect/tools/cl/has_flags.lua @@ -83,7 +83,8 @@ end function main(flags, opt) -- attempt to check it from the argument list - if _check_from_arglist(flags, opt) then + opt = opt or {} + if not opt.tryrun and _check_from_arglist(flags, opt) then return true end diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua index f7cf1d29e..b8e63423a 100644 --- a/xmake/modules/detect/tools/gcc/has_flags.lua +++ b/xmake/modules/detect/tools/gcc/has_flags.lua @@ -101,10 +101,11 @@ end function main(flags, opt) -- is linker? + opt = opt or {} local islinker = _islinker(flags, opt) -- attempt to check it from the argument list - if _check_from_arglist(flags, opt, islinker) then + if not opt.tryrun and _check_from_arglist(flags, opt, islinker) then return true end diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 0095444ed..b00d059b9 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -371,8 +371,8 @@ function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support"}) and - compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support"}) then + if compinst:has_flags("-x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false -- cgit v1.3.1 From a230a29949612a49fb9acb06988518e0d84ecfe1 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:35:29 +0800 Subject: add some comments --- xmake/rules/c++/modules/modules_support/common.lua | 42 +++++++++++++++------- xmake/rules/c++/modules/modules_support/msvc.lua | 1 + 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 7f6f7aa43..11f7bf897 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -267,18 +267,38 @@ function find_angle_header_file(target, file) return p end -function fallback_generate_dependencies(target, jsonfile, sourcefile) - local output = { - version = 0, - revision = 0, - rules = {} - } - - local rule = { - outputs = { - jsonfile +-- https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html +--[[ +{ + "version": 1, + "revision": 0, + "rules": [ + { + "primary-output": "use-header.mpp.o", + "requires": [ + { + "logical-name": "", + "source-path": "/path/to/found/header.hpp", + "unique-on-source-path": true, + "lookup-method": "include-angle" + } + ] + }, + { + "primary-output": "header.hpp.bmi", + "provides": [ + { + "logical-name": "header.hpp", + "source-path": "/path/to/found/header.hpp", + "unique-on-source-path": true, } + ] } + ] +}]] +function fallback_generate_dependencies(target, jsonfile, sourcefile) + local output = {version = 0, revision = 0, rules = {}} + local rule = {outputs = {jsonfile}} rule["primary-output"] = target:objectfile(sourcefile) local module_name @@ -290,11 +310,9 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) if not module_name then module_name = line:match("export%s+module%s+(.+)%s*;") end - local module_depname = line:match("import%s+(.+)%s*;") if module_depname then local module_dep = {} - -- partition? import :xxx; if module_depname:startswith(":") then module_depname = module_name .. module_depname diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 63e445df9..b7045fc73 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -99,6 +99,7 @@ function generate_dependencies(target, sourcebatch, opt) if scandependenciesflag then local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + io.cat(jsonfile) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end -- cgit v1.3.1 From b8c3621afb10f6dd7ee483ed8bebfb039cd11d7e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:38:05 +0800 Subject: add more comments --- xmake/rules/c++/modules/modules_support/common.lua | 27 ++++++++++++++++++++++ xmake/rules/c++/modules/modules_support/msvc.lua | 1 - 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 11f7bf897..00f7ae6f3 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -128,6 +128,33 @@ function load_moduleinfos(target, sourcebatch, opt) end -- parse module dependency data +--[[ +{ + "build/.objs/stl_headerunit/linux/x86_64/release/src/hello.mpp.o" = { + requires = { + iostream = { + method = "include-angle", + unique = true, + path = "/usr/include/c++/11/iostream" + } + }, + provides = { + hello = { + bmi = "build/.gens/stl_headerunit/linux/x86_64/release/rules/modules/cache/hello.gcm", + sourcefile = "src/hello.mpp" + } + } + }, + "build/.objs/stl_headerunit/linux/x86_64/release/src/main.cpp.o" = { + requires = { + hello = { + method = "by-name", + unique = false, + path = "build/.gens/stl_headerunit/linux/x86_64/release/rules/modules/cache/hello.gcm" + } + } + } +}]] function parse_dependency_data(target, moduleinfos, opt) local modules local cachedir = modules_cachedir(target) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b7045fc73..63e445df9 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -99,7 +99,6 @@ function generate_dependencies(target, sourcebatch, opt) if scandependenciesflag then local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - io.cat(jsonfile) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end -- cgit v1.3.1 From e581f5c19ad1feeed70e26d294c114c48ade00da Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:40:16 +0800 Subject: optimize to get headerunits info --- xmake/rules/c++/modules/xmake.lua | 18 ++++++++---------- xmake/rules/qt/env/xmake.lua | 4 ++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 9a7599358..a1d6fdca4 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -89,20 +89,18 @@ rule("c++.build.modules.builder") sourcebatch.dependfiles = {} common.patch_sourcebatch(target, sourcebatch, opt) - -- get headerunits info, TODO maybe need optimize it + -- get headerunits info local headerunits local modules = target:data("cxx.modules") for _, objectfile in ipairs(sourcebatch.objectfiles) do - for obj, m in pairs(modules) do - if obj == objectfile then - for name, r in pairs(m.requires) do - if r.method ~= "by-name" then - headerunits = headerunits or {} - local unittype = r.method == "include-angle" and ":angle" or ":quote" - table.append(headerunits, {name = name, path = r.path, type = unittype, stl = stl_headers.is_stl_header(name)}) - end + local m = modules[objectfile] + if m then + for name, r in pairs(m.requires) do + if r.method ~= "by-name" then + headerunits = headerunits or {} + local unittype = r.method == "include-angle" and ":angle" or ":quote" + table.insert(headerunits, {name = name, path = r.path, type = unittype, stl = stl_headers.is_stl_header(name)}) end - break end end end diff --git a/xmake/rules/qt/env/xmake.lua b/xmake/rules/qt/env/xmake.lua index 592ef07d9..815ae49cb 100644 --- a/xmake/rules/qt/env/xmake.lua +++ b/xmake/rules/qt/env/xmake.lua @@ -34,9 +34,9 @@ rule("qt.env") local qmlimportpath = target:values("qt.env.qmlimportpath") or {} if target:is_plat("windows") or (target:is_plat("mingw") and is_host("windows")) then target:add("runenvs", "PATH", qt.bindir) - table.append(qmlimportpath, qt.qmldir) + table.insert(qmlimportpath, qt.qmldir) -- add targetdir in QML2_IMPORT_PATH in case of the user have qml plugins - table.append(qmlimportpath, target:targetdir()) + table.insert(qmlimportpath, target:targetdir()) target:set("runenv", "QML_IMPORT_TRACE", "1") elseif target:is_plat("msys", "cygwin") then raise("please run `xmake f -p mingw --mingw=/mingw64` to support Qt/Mingw64 on Msys!") -- cgit v1.3.1 From fc011e7ae96d00c209550022ce44f66ec002a474 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:43:34 +0800 Subject: rename sourcebatch to headerunits --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- xmake/rules/c++/modules/modules_support/common.lua | 1 - xmake/rules/c++/modules/modules_support/gcc.lua | 4 ++-- xmake/rules/c++/modules/modules_support/msvc.lua | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index b00d059b9..c53716d51 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -128,7 +128,7 @@ function generate_dependencies(target, sourcebatch, opt) end -- generate target header units -function generate_headerunits(target, batchcmds, sourcebatch, opt) +function generate_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -143,7 +143,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) local objectfiles = {} local public_flags = {} local private_flags = {} - for _, headerunit in ipairs(sourcebatch) do + for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 00f7ae6f3..331f1bea5 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -263,7 +263,6 @@ function sort_modules_by_dependencies(objectfiles, modules) table.insert(nodes, {marked = false, tempmarked = false, objectfile = objectfile}) end end - while _topological_sort_has_node_without_mark(nodes) do local node = _topological_sort_get_first_unmarked_node(nodes) _topological_sort_visit(node, nodes, modules, output) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index c270adcf9..afa8d249d 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -145,7 +145,7 @@ function generate_dependencies(target, sourcebatch, opt) end -- generate target header units -function generate_headerunits(target, batchcmds, sourcebatch, opt) +function generate_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) @@ -153,7 +153,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) -- build headerunits local objectfiles = {} - for _, headerunit in ipairs(sourcebatch) do + for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 63e445df9..37bcf0b89 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -110,7 +110,7 @@ function generate_dependencies(target, sourcebatch, opt) end -- generate target header units -function generate_headerunits(target, batchcmds, sourcebatch, opt) +function generate_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -131,7 +131,7 @@ function generate_headerunits(target, batchcmds, sourcebatch, opt) local objectfiles = {} local public_flags = {} local private_flags = {} - for _, headerunit in ipairs(sourcebatch) do + for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) -- cgit v1.3.1 From 88c91ec3ff285ba148a04a01e8e32bdf2b186dc5 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:45:59 +0800 Subject: use projectdir var --- xmake/rules/c++/modules/modules_support/clang.lua | 3 ++- xmake/rules/c++/modules/modules_support/gcc.lua | 14 ++++++++------ xmake/rules/c++/modules/modules_support/msvc.lua | 3 ++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index c53716d51..00434ef81 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -143,6 +143,7 @@ function generate_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local public_flags = {} local private_flags = {} + local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) @@ -150,7 +151,7 @@ function generate_headerunits(target, batchcmds, headerunits, opt) local outdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else outdir = path.join(cachedir, path.directory(headerunit.path)) end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index afa8d249d..e46ff6d7f 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -153,6 +153,7 @@ function generate_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local objectfiles = {} + local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) @@ -160,7 +161,7 @@ function generate_headerunits(target, batchcmds, headerunits, opt) local outdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else outdir = path.join(cachedir, path.directory(headerunit.path)) end @@ -174,14 +175,14 @@ function generate_headerunits(target, batchcmds, headerunits, opt) os.mkdir(path.directory(objectfile)) end - if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then local args = { "-c" } if headerunit.type == ":quote" then table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) - _add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, project.directory())), path.absolute(bmifile, project.directory())) + _add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, projectdir)), path.absolute(bmifile, projectdir)) elseif headerunit.type == ":angle" then table.join2(args, { "-x", "c++-system-header", headerunit.name }) - _add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, project.directory())) + _add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, projectdir)) end batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -193,7 +194,7 @@ function generate_headerunits(target, batchcmds, headerunits, opt) end else local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, project.directory())) then + if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then if not os.isfile(bmifile) then local args = { "-c", "-x", "c++-system-header", headerunit.name } @@ -214,6 +215,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() local common_args = {"-x", "c++"} + local projectdir = os.projectdir() for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then @@ -226,7 +228,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) local bmifile = provide.bmi - if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, project.directory())) then + if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then table.join2(args, {"-c", provide.sourcefile}) batchcmds:add_depfiles(provide.sourcefile) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 37bcf0b89..02c48524f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -131,13 +131,14 @@ function generate_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local public_flags = {} local private_flags = {} + local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do if not headerunit.stl then local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) local outputdir if headerunit.type == ":quote" then - outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, project.directory()))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) end -- cgit v1.3.1 From 65a9b356196552f35a1414691a3f328cc3152bff Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:46:31 +0800 Subject: add mapper comments --- xmake/rules/c++/modules/modules_support/gcc.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e46ff6d7f..2b21a7091 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -37,6 +37,11 @@ function _get_module_mapper() end -- add a module or header unit into the mapper +-- +-- e.g +-- /usr/include/c++/11/iostream build/.gens/stl_headerunit/linux/x86_64/release/stlmodules/cache/iostream.gcm +-- hello build/.gens/stl_headerunit/linux/x86_64/release/rules/modules/cache/hello.gcm +-- function _add_module_to_mapper(file, module, bmi) for line in io.lines(file) do if line:startswith(module .. " ") then -- cgit v1.3.1 From afade6b03c87a2534a01cf9e9ed9763e97208e34 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Aug 2022 00:57:34 +0800 Subject: update dep flags --- xmake/rules/c++/modules/modules_support/clang.lua | 8 ++++---- xmake/rules/c++/modules/modules_support/msvc.lua | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 00434ef81..7d841a2be 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -208,12 +208,12 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local modulefileflag = get_modulefileflag(target) -- append deps modules - local flags = {} for _, dep in ipairs(target:orderdeps()) do - table.join2(flags, dep:data("cxx.modules.flags")) + local flags = dep:data("cxx.modules.flags") + if flags then + target:add("cxxflags", flags, {force = true, expand = false}) + end end - flags = table.unique(flags) - target:add("cxxflags", flags, {force = true, expand = false}) local common_args = {modulecachepathflag .. cachedir} for _, objectfile in ipairs(objectfiles) do diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 02c48524f..c2351371f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -196,7 +196,10 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) -- append deps modules for _, dep in ipairs(target:orderdeps()) do - target:add("cxxflags", dep:data("cxx.modules.flags"), {force = true, expand = false}) + local flags = dep:data("cxx.modules.flags") + if flags then + target:add("cxxflags", flags, {force = true, expand = false}) + end end -- compile module files to bmi files -- cgit v1.3.1 From 92bd964f8e420a2bb72fd82a17603b5fddc865d3 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 4 Aug 2022 22:44:13 +0200 Subject: Insert deps includedirs/sysincludedirs when search angle header files --- xmake/rules/c++/modules/modules_support/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 331f1bea5..a8b36e0fa 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -279,7 +279,7 @@ end function find_angle_header_file(target, file) local headerpaths = modules_support(target).toolchain_includedirs(target) for _, dep in ipairs(target:orderdeps()) do - table.insert(headerpaths, dep:scriptdir()) + table.insert(headerpaths, dep:get("sysincludedirs") or dep:get("includedirs")) end for _, pkg in ipairs(target:pkgs()) do local includedirs = pkg:get("sysincludedirs") or pkg:get("includedirs") -- cgit v1.3.1 From 6c27288e6156c41ad754c7a195faaf40dcce0c18 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 4 Aug 2022 23:27:28 +0200 Subject: Fix bmi generation path when module is generated by build chain --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- xmake/rules/c++/modules/modules_support/gcc.lua | 2 +- xmake/rules/c++/modules/modules_support/msvc.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 7d841a2be..fd71b298f 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -112,7 +112,7 @@ function generate_dependencies(target, sourcebatch, opt) depend.on_changed(function() progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) if not os.isdir(outdir) then os.mkdir(outdir) end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 2b21a7091..dba8b7e79 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -128,7 +128,7 @@ function generate_dependencies(target, sourcebatch, opt) depend.on_changed(function() progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir())))) + local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) if not os.isdir(outdir) then os.mkdir(outdir) end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index c2351371f..fa5741676 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -90,7 +90,7 @@ function generate_dependencies(target, sourcebatch, opt) local dependfile = target:dependfile(sourcefile) depend.on_changed(function () progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) - local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir()))) + local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, projectdir))) if not os.isdir(outputdir) then os.mkdir(outputdir) end -- cgit v1.3.1 From d2d7292907f6aecbcb0b52aca4897bc7fbaf94cd Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 4 Aug 2022 23:27:42 +0200 Subject: Improve header unit support --- xmake/rules/c++/modules/modules_support/clang.lua | 114 +++++++++++++--------- xmake/rules/c++/modules/modules_support/gcc.lua | 112 +++++++++++---------- xmake/rules/c++/modules/modules_support/msvc.lua | 110 ++++++++++++--------- xmake/rules/c++/modules/xmake.lua | 26 +++-- 4 files changed, 214 insertions(+), 148 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index fd71b298f..e023acccb 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -127,13 +127,44 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target header units -function generate_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units +function generate_stl_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") - local cachedir = common.modules_cachedir(target) + + -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) + + -- get headerunits flags + local modulecachepathflag = get_modulecachepathflag(target) + local modulefileflag = get_modulefileflag(target) + + -- build headerunits + local projectdir = os.projectdir() + local flags = {} + for i, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end + + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + + table.insert(flags, modulefileflag .. bmifile) + end + return flags +end + +-- generate target user header units +function generate_user_headerunits(target, batchcmds, headerunits, opt) + local compinst = target:compiler("cxx") assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + -- get cachedirs + local cachedir = common.modules_cachedir(target) + -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleflag = get_emitmoduleflag(target) @@ -141,65 +172,52 @@ function generate_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local objectfiles = {} - local public_flags = {} - local private_flags = {} + local flags = {} local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) - - local outdir - if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - outdir = path.join(cachedir, path.directory(headerunit.path)) - end - if not os.isdir(outdir) then - os.mkdir(outdir) - end - - local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) - local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} - if headerunit.type == ":quote" then - table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) - elseif headerunit.type == ":angle" then - table.join2(args, {"-x", "c++-system-header", headerunit.name}) - end + local outdir + if headerunit.type == ":quote" then + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outdir = path.join(cachedir, path.directory(headerunit.path)) + end + if not os.isdir(outdir) then + os.mkdir(outdir) + end - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) + local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} + if headerunit.type == ":quote" then + table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) + elseif headerunit.type == ":angle" then + table.join2(args, {"-x", "c++-system-header", headerunit.name}) + end - table.insert(public_flags, modulefileflag .. bmifile) - else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if not os.isfile(bmifile) then - local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - end + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) - table.insert(private_flags, modulefileflag .. bmifile) - end + table.insert(flags, modulefileflag .. bmifile) end - return public_flags, private_flags + return flags end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") + + -- get cachedirs local cachedir = common.modules_cachedir(target) -- get modules flags diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index dba8b7e79..23e89a30b 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -149,77 +149,91 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target header units -function generate_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units +function generate_stl_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") - local cachedir = common.modules_cachedir(target) - local stlcachedir = common.stlmodules_cachedir(target) local mapper_file = _get_module_mapper() + -- get cachedirs + local stlcachedir = common.stlmodules_cachedir(target) + -- build headerunits - local objectfiles = {} local projectdir = os.projectdir() - for _, headerunit in ipairs(headerunits) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) + for i, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then + local args = { "-c", "-x", "c++-system-header", headerunit.name } - local outdir - if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - outdir = path.join(cachedir, path.directory(headerunit.path)) - end - if not os.isdir(outdir) then - os.mkdir(outdir) - end + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + end + end +end - if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then - local args = { "-c" } - if headerunit.type == ":quote" then - table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name }) - _add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, projectdir)), path.absolute(bmifile, projectdir)) - elseif headerunit.type == ":angle" then - table.join2(args, { "-x", "c++-system-header", headerunit.name }) - _add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, projectdir)) - end +-- generate target user header units +function generate_user_headerunits(target, batchcmds, headerunits, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + -- get cachedirs + local cachedir = common.modules_cachedir(target) - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - end + -- build headerunits + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, projectdir) + local objectfile = target:objectfile(file) + + local outdir + if headerunit.type == ":quote" then + outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then - if not os.isfile(bmifile) then - local args = { "-c", "-x", "c++-system-header", headerunit.name } + outdir = path.join(cachedir, path.directory(headerunit.path)) + end + if not os.isdir(outdir) then + os.mkdir(outdir) + end - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - end - end + local args = { "-c" } + local headerunit_path + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) + headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + -- if path is relative then its a subtarget path + headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) + end + + if _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) then + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) end end end -- build module files function build_modules(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() local common_args = {"-x", "c++"} + + -- get cachedirs + local cachedir = common.modules_cachedir(target) + local projectdir = os.projectdir() for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index fa5741676..5006b4d9f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -109,8 +109,8 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target header units -function generate_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units +function generate_stl_headerunits(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -123,62 +123,84 @@ function generate_headerunits(target, batchcmds, headerunits, opt) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") -- get cachedirs - local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) -- build headerunits local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} - local public_flags = {} - local private_flags = {} - local projectdir = os.projectdir() + local flags = {} for _, headerunit in ipairs(headerunits) do - if not headerunit.stl then - local file = path.relative(headerunit.path, target:scriptdir()) - local objectfile = target:objectfile(file) - local outputdir - if headerunit.type == ":quote" then - outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) - end - if not os.isdir(outputdir) then - os.mkdir(outputdir) - end + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) + end - local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) - end + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) - local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} + table.join2(flags, flag) + end + return flags +end - batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) +-- generate target user header units +function generate_user_headerunits(target, batchcmds, headerunits, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") - local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} - table.join2(public_flags, flag) - target:add("objectfiles", objectfile) - else - local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = 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!") - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) + -- get cachedirs + local cachedir = common.modules_cachedir(target) - local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} - table.join2(private_flags, flag) + -- build headerunits + local common_args = {"/TP", exportheaderflag, "/c"} + local objectfiles = {} + local flags = {} + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) end + + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + if not os.isdir(path.directory(objectfile)) then + os.mkdir(path.directory(objectfile)) + end + + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + + batchcmds:add_depfiles(headerunit.path) + batchcmds:set_depmtime(os.mtime(bmifile)) + batchcmds:set_depcache(target:dependfile(bmifile)) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + + local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} + table.join2(flags, flag) + target:add("objectfiles", objectfile) end - return public_flags, private_flags + return flags end -- build module files diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index a1d6fdca4..7c68f25e0 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -91,15 +91,22 @@ rule("c++.build.modules.builder") -- get headerunits info local headerunits + local stl_headerunits local modules = target:data("cxx.modules") for _, objectfile in ipairs(sourcebatch.objectfiles) do local m = modules[objectfile] if m then for name, r in pairs(m.requires) do if r.method ~= "by-name" then - headerunits = headerunits or {} local unittype = r.method == "include-angle" and ":angle" or ":quote" - table.insert(headerunits, {name = name, path = r.path, type = unittype, stl = stl_headers.is_stl_header(name)}) + + if stl_headers.is_stl_header(name) then + stl_headerunits = stl_headerunits or {} + table.insert(stl_headerunits, {name = name, path = r.path, type = unittype}) + else + headerunits = headerunits or {} + table.insert(headerunits, {name = name, path = r.path, type = unittype,}) + end end end end @@ -107,17 +114,22 @@ rule("c++.build.modules.builder") -- generate headerunits local headerunits_flags - local private_headerunits_flags local modules_support = common.modules_support(target) + -- build stl header units as other headerunits may need them + if stl_headerunits then + headerunits_flags = headerunits_flags or {} + table.join2(headerunits_flags, modules_support.generate_stl_headerunits(target, batchcmds, stl_headerunits, opt)) + + -- force STL header unit generation + batchcmds:runcmds(opt) + end if headerunits then - headerunits_flags, private_headerunits_flags = modules_support.generate_headerunits(target, batchcmds, headerunits, opt) + headerunits_flags = headerunits_flags or {} + table.join2(headerunits_flags, modules_support.generate_user_headerunits(target, batchcmds, headerunits, opt)) end if headerunits_flags then target:add("cxxflags", headerunits_flags, {force = true, expand = false}) end - if private_headerunits_flags then - target:add("cxxflags", private_headerunits_flags, {force = true, expand = false}) - end -- topological sort local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) -- cgit v1.3.1 From bd2fc3f699e468604bdf489c3348d22962f14012 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 03:26:43 +0200 Subject: Use batchcmds:mkdir instead of os.mkdir when possible --- xmake/rules/c++/modules/modules_support/clang.lua | 6 +++--- xmake/rules/c++/modules/modules_support/gcc.lua | 6 +++--- xmake/rules/c++/modules/modules_support/msvc.lua | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index e023acccb..4ab3c3892 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -185,13 +185,13 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) outdir = path.join(cachedir, path.directory(headerunit.path)) end if not os.isdir(outdir) then - os.mkdir(outdir) + batchcmds:mkdir(outdir) end local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} @@ -238,7 +238,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local m = modules[objectfile] if m then if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = { emitmoduleinterfaceflag } diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 23e89a30b..a3ef5c8a8 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -194,13 +194,13 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) outdir = path.join(cachedir, path.directory(headerunit.path)) end if not os.isdir(outdir) then - os.mkdir(outdir) + batchcmds:mkdir(outdir) end local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = { "-c" } @@ -239,7 +239,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local m = modules[objectfile] if m then if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = {"-o", objectfile} diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 5006b4d9f..abc7f7319 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -177,13 +177,13 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) end if not os.isdir(outputdir) then - os.mkdir(outputdir) + batchcmds:mkdir(outputdir) end local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} @@ -230,7 +230,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local m = modules[objectfile] if m then if not os.isdir(path.directory(objectfile)) then - os.mkdir(path.directory(objectfile)) + batchcmds:mkdir(path.directory(objectfile)) end local args = {"/c", "/Fo" .. objectfile} -- cgit v1.3.1 From 886364620b81ad0024e5e98bee9b5a44e6c6f160 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 03:30:52 +0200 Subject: Remove useless isdir checks --- xmake/rules/c++/modules/modules_support/clang.lua | 12 +++--------- xmake/rules/c++/modules/modules_support/gcc.lua | 12 +++--------- xmake/rules/c++/modules/modules_support/msvc.lua | 12 +++--------- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 4ab3c3892..cc6e2f927 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -184,15 +184,11 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) else outdir = path.join(cachedir, path.directory(headerunit.path)) end - if not os.isdir(outdir) then - batchcmds:mkdir(outdir) - end + batchcmds:mkdir(outdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} if headerunit.type == ":quote" then @@ -237,9 +233,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = { emitmoduleinterfaceflag } local bmiflags = {} diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index a3ef5c8a8..1c53d22b5 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -193,15 +193,11 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) else outdir = path.join(cachedir, path.directory(headerunit.path)) end - if not os.isdir(outdir) then - batchcmds:mkdir(outdir) - end + batchcmds:mkdir(outdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = { "-c" } local headerunit_path @@ -238,9 +234,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = {"-o", objectfile} for name, provide in pairs(m.provides) do diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index abc7f7319..93eef7c8c 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -176,15 +176,11 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) else outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) end - if not os.isdir(outputdir) then - batchcmds:mkdir(outputdir) - end + batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -229,9 +225,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then - if not os.isdir(path.directory(objectfile)) then - batchcmds:mkdir(path.directory(objectfile)) - end + batchcmds:mkdir(path.directory(objectfile)) local args = {"/c", "/Fo" .. objectfile} local bmiflags = {} -- cgit v1.3.1 From b370625fbf37fe5e957677ec4c04ec3503d0da90 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 04:40:47 +0200 Subject: Handle angle relative path --- xmake/rules/c++/modules/modules_support/msvc.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 93eef7c8c..04d34f02c 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -174,7 +174,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) if headerunit.type == ":quote" then outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3)) + -- if path is relative then its a subtarget path + outputdir = path.join(cachedir, path.is_absolute(headerunit.path) and path.directory(headerunit.path):sub(3) or headerunit.path) end batchcmds:mkdir(outputdir) -- cgit v1.3.1 From 9051b99608fe2f339eea7ac4c9eab8b799e230df Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 04:41:46 +0200 Subject: Move headerunits extracting into a dedicated function --- xmake/rules/c++/modules/modules_support/common.lua | 31 ++++++++++++++++++++-- xmake/rules/c++/modules/modules_support/msvc.lua | 2 +- xmake/rules/c++/modules/xmake.lua | 28 +++---------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index a8b36e0fa..18647ded1 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -26,6 +26,7 @@ import("core.tool.compiler") import("core.cache.memcache", {alias = "_memcache"}) import("core.project.project") import("lib.detect.find_file") +import("stl_headers") -- get memcache function memcache() @@ -53,12 +54,38 @@ function modules_cachedir(target) return cachedir end +-- get headerunits info +function get_headerunits(target, sourcebatch) + local headerunits + local stl_headerunits + local modules = target:data("cxx.modules") + for _, objectfile in ipairs(sourcebatch.objectfiles) do + local m = modules[objectfile] + if m then + for name, r in pairs(m.requires) do + if r.method ~= "by-name" then + local unittype = r.method == "include-angle" and ":angle" or ":quote" + + if stl_headers.is_stl_header(name) then + stl_headerunits = stl_headerunits or {} + table.insert(stl_headerunits, {name = name, path = r.path, type = unittype}) + else + headerunits = headerunits or {} + table.insert(headerunits, {name = name, path = r.path, type = unittype}) + end + end + end + end + end + return headerunits, stl_headerunits +end + -- patch sourcebatch function patch_sourcebatch(target, sourcebatch, opt) local cachedir = modules_cachedir(target) sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} + sourcebatch.objectfiles = {} + sourcebatch.dependfiles = {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 04d34f02c..2c3818995 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -183,7 +183,7 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) - local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + local args = {headernameflag .. headerunit.type, path.normalize(headerunit.path), ifcoutputflag, outputdir, "/Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 7c68f25e0..45ba38ca8 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -82,35 +82,14 @@ rule("c++.build.modules.builder") return end - -- patch sourcebatch import("modules_support.common") import("modules_support.stl_headers") - sourcebatch.objectfiles = {} - sourcebatch.dependfiles = {} + + -- patch sourcebatch common.patch_sourcebatch(target, sourcebatch, opt) -- get headerunits info - local headerunits - local stl_headerunits - local modules = target:data("cxx.modules") - for _, objectfile in ipairs(sourcebatch.objectfiles) do - local m = modules[objectfile] - if m then - for name, r in pairs(m.requires) do - if r.method ~= "by-name" then - local unittype = r.method == "include-angle" and ":angle" or ":quote" - - if stl_headers.is_stl_header(name) then - stl_headerunits = stl_headerunits or {} - table.insert(stl_headerunits, {name = name, path = r.path, type = unittype}) - else - headerunits = headerunits or {} - table.insert(headerunits, {name = name, path = r.path, type = unittype,}) - end - end - end - end - end + local headerunits, stl_headerunits = common.get_headerunits(target, sourcebatch) -- generate headerunits local headerunits_flags @@ -132,6 +111,7 @@ rule("c++.build.modules.builder") end -- topological sort + local modules = target:data("cxx.modules") local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) modules_support.build_modules(target, batchcmds, objectfiles, modules, opt) end) -- cgit v1.3.1 From 4cdf4838df5d5903b8d2ac31c9a169c5d88a2ebb Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 04:44:30 +0200 Subject: outputdir is never nil --- xmake/rules/c++/modules/modules_support/msvc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 2c3818995..3f371c5c7 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -180,10 +180,10 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + local bmifile = path.join(outputdir, bmifilename) batchcmds:mkdir(path.directory(objectfile)) - local args = {headernameflag .. headerunit.type, path.normalize(headerunit.path), ifcoutputflag, outputdir, "/Fo" .. objectfile} + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) -- cgit v1.3.1 From e4179556134ffba995299eb3e949c48ad80d8678 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 05:11:14 +0200 Subject: Fix incorrect usage of set_depmtime/set_depcache --- xmake/rules/c++/modules/modules_support/clang.lua | 35 ++++++++++++++--------- xmake/rules/c++/modules/modules_support/gcc.lua | 29 ++++++++++++------- xmake/rules/c++/modules/modules_support/msvc.lua | 34 +++++++++++++--------- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index cc6e2f927..c91decb97 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -141,6 +141,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() local flags = {} + local bmifiles = {} + local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then @@ -149,11 +151,12 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - table.insert(flags, modulefileflag .. bmifile) + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -174,6 +177,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local flags = {} local projectdir = os.projectdir() + local bmifiles = {} + local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) @@ -201,11 +206,13 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) table.insert(flags, modulefileflag .. bmifile) + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -229,7 +236,10 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end + -- build modules local common_args = {modulecachepathflag .. cachedir} + local bmifiles = {} + local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then @@ -237,34 +247,33 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local args = { emitmoduleinterfaceflag } local bmiflags = {} - local bmifiles = {} + local bmifiles_ = {} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) local bmifile = provide.bmi table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) - table.join2(bmifiles, bmifile) + table.append(bmifiles_, bmifile) batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) table.join2(bmiflags, {modulefileflag .. bmifile}) + depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles, {"-c", "-o", objectfile})) - - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles_, {"-c", "-o", objectfile})) target:add("cxxflags", bmiflags, {public = true, force = true}) target:add("objectfiles", objectfile) for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) end + table.join2(bmifiles, bmifiles_) end end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 1c53d22b5..c23ced122 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -159,6 +159,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() + local bmifiles = {} + local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then @@ -166,11 +168,12 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) end + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) end -- generate target user header units @@ -183,6 +186,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() + local bmifiles = {} + local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) local objectfile = target:objectfile(file) @@ -215,10 +220,12 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) end + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) end -- build module files @@ -230,7 +237,10 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) -- get cachedirs local cachedir = common.modules_cachedir(target) + -- build modules local projectdir = os.projectdir() + local bmifiles = {} + local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then @@ -245,19 +255,18 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) table.join2(args, {"-c", provide.sourcefile}) batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) end + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) - target:add("objectfiles", objectfile) end end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 3f371c5c7..89cc35f6b 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -129,6 +129,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} local flags = {} + local bmifiles = {} + local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then @@ -137,12 +139,14 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) end - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} table.join2(flags, flag) + + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -167,6 +171,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local flags = {} local projectdir = os.projectdir() + local bmifiles = {} + local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) @@ -188,15 +194,16 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} table.join2(flags, flag) target:add("objectfiles", objectfile) + + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -221,8 +228,10 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end - -- compile module files to bmi files + -- build modules local common_args = {"/TP"} + local bmifiles = {} + local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m then @@ -237,17 +246,14 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) table.join2(args, {interfaceflag, ifcoutputflag, bmifile, provide.sourcefile}) batchcmds:add_depfiles(provide.sourcefile) - batchcmds:set_depmtime(os.mtime(bmifile)) - batchcmds:set_depcache(target:dependfile(bmifile)) table.join2(bmiflags, {referenceflag, name .. "=" .. path.filename(bmifile)}) + table.append(bmifiles, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args, bmi_args), {envs = vcvars}) - batchcmds:set_depmtime(os.mtime(objectfile)) - batchcmds:set_depcache(target:dependfile(objectfile)) - target:add("cxxflags", bmiflags, {force = true, expand = false}) for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) @@ -255,6 +261,8 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) target:add("objectfiles", objectfile) end end + batchcmds:set_depmtime(depmtime) + batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() -- cgit v1.3.1 From 279689863b3ced10d7d1639b77ec57c70db11fde Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 05:33:21 +0200 Subject: Do not insert duplicate header unit --- xmake/rules/c++/modules/modules_support/common.lua | 8 ++++++-- xmake/rules/c++/modules/xmake.lua | 3 --- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 18647ded1..8d3c8456d 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -68,10 +68,14 @@ function get_headerunits(target, sourcebatch) if stl_headers.is_stl_header(name) then stl_headerunits = stl_headerunits or {} - table.insert(stl_headerunits, {name = name, path = r.path, type = unittype}) + if not table.find_if(stl_headerunits, function(i, v) return v.name == name end) then + table.insert(stl_headerunits, {name = name, path = r.path, type = unittype}) + end else headerunits = headerunits or {} - table.insert(headerunits, {name = name, path = r.path, type = unittype}) + if not table.find_if(headerunits, function(i, v) return v.name == name end) then + table.insert(headerunits, {name = name, path = r.path, type = unittype}) + end end end end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 45ba38ca8..4eae5f522 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -98,9 +98,6 @@ rule("c++.build.modules.builder") if stl_headerunits then headerunits_flags = headerunits_flags or {} table.join2(headerunits_flags, modules_support.generate_stl_headerunits(target, batchcmds, stl_headerunits, opt)) - - -- force STL header unit generation - batchcmds:runcmds(opt) end if headerunits then headerunits_flags = headerunits_flags or {} -- cgit v1.3.1 From 913fecaf3b83198105cd56d10156b1adbc901a7e Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 05:34:45 +0200 Subject: Use table.insert instead of table.append --- xmake/rules/c++/modules/modules_support/clang.lua | 6 +++--- xmake/rules/c++/modules/modules_support/gcc.lua | 6 +++--- xmake/rules/c++/modules/modules_support/msvc.lua | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index c91decb97..90d74b654 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -152,7 +152,7 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) end table.insert(flags, modulefileflag .. bmifile) - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -208,7 +208,7 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:add_depfiles(headerunit.path) table.insert(flags, modulefileflag .. bmifile) - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -253,7 +253,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local bmifile = provide.bmi table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) - table.append(bmifiles_, bmifile) + table.insert(bmifiles_, bmifile) batchcmds:add_depfiles(provide.sourcefile) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index c23ced122..700e92210 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -169,7 +169,7 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -221,7 +221,7 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:add_depfiles(headerunit.path) end - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -256,7 +256,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:add_depfiles(provide.sourcefile) end - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 89cc35f6b..22dc4485f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -142,7 +142,7 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} table.join2(flags, flag) - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -199,7 +199,7 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) table.join2(flags, flag) target:add("objectfiles", objectfile) - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -248,7 +248,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:add_depfiles(provide.sourcefile) table.join2(bmiflags, {referenceflag, name .. "=" .. path.filename(bmifile)}) - table.append(bmifiles, bmifile) + table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end -- cgit v1.3.1 From 08bf176c09948d0a9662ca72b804e42e90ad341d Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 05:38:34 +0200 Subject: Remove incorrect usage of set_depcache --- xmake/rules/c++/modules/modules_support/clang.lua | 15 +++------------ xmake/rules/c++/modules/modules_support/gcc.lua | 9 --------- xmake/rules/c++/modules/modules_support/msvc.lua | 9 --------- 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 90d74b654..2cc4b0bb4 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -141,7 +141,6 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() local flags = {} - local bmifiles = {} local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -152,11 +151,9 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) end table.insert(flags, modulefileflag .. bmifile) - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -177,7 +174,6 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local flags = {} local projectdir = os.projectdir() - local bmifiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) @@ -208,11 +204,9 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:add_depfiles(headerunit.path) table.insert(flags, modulefileflag .. bmifile) - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -238,7 +232,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) -- build modules local common_args = {modulecachepathflag .. cachedir} - local bmifiles = {} local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -247,13 +240,13 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local args = { emitmoduleinterfaceflag } local bmiflags = {} - local bmifiles_ = {} + local bmifiles = {} for name, provide in pairs(m.provides) do batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) local bmifile = provide.bmi table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) - table.insert(bmifiles_, bmifile) + table.insert(bmifiles, bmifile) batchcmds:add_depfiles(provide.sourcefile) @@ -262,18 +255,16 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles_, {"-c", "-o", objectfile})) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles, {"-c", "-o", objectfile})) target:add("cxxflags", bmiflags, {public = true, force = true}) target:add("objectfiles", objectfile) for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) end - table.join2(bmifiles, bmifiles_) end end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 700e92210..ee4013d3e 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -159,7 +159,6 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() - local bmifiles = {} local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -169,11 +168,9 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) end -- generate target user header units @@ -186,7 +183,6 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) -- build headerunits local projectdir = os.projectdir() - local bmifiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) @@ -221,11 +217,9 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:add_depfiles(headerunit.path) end - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) end -- build module files @@ -239,7 +233,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) -- build modules local projectdir = os.projectdir() - local bmifiles = {} local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -256,7 +249,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:add_depfiles(provide.sourcefile) end - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -266,7 +258,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 22dc4485f..f3437eeab 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -129,7 +129,6 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} local flags = {} - local bmifiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -142,11 +141,9 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} table.join2(flags, flag) - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -171,7 +168,6 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) local objectfiles = {} local flags = {} local projectdir = os.projectdir() - local bmifiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) @@ -199,11 +195,9 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) table.join2(flags, flag) target:add("objectfiles", objectfile) - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) return flags end @@ -230,7 +224,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) -- build modules local common_args = {"/TP"} - local bmifiles = {} local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -248,7 +241,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:add_depfiles(provide.sourcefile) table.join2(bmiflags, {referenceflag, name .. "=" .. path.filename(bmifile)}) - table.insert(bmifiles, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -262,7 +254,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end batchcmds:set_depmtime(depmtime) - batchcmds:set_depcache(target:dependfile(bmifiles)) end function get_bmi_extension() -- cgit v1.3.1 From cf4a7193ea34e3f82d710114343c7fb1f00e261d Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 06:11:54 +0200 Subject: Assert on multiple provides --- xmake/rules/c++/modules/modules_support/clang.lua | 43 ++++++++++++----------- xmake/rules/c++/modules/modules_support/gcc.lua | 33 ++++++++++------- xmake/rules/c++/modules/modules_support/msvc.lua | 34 ++++++++++-------- 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 2cc4b0bb4..734fa5a4d 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -235,33 +235,34 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then - batchcmds:mkdir(path.directory(objectfile)) - - local args = { emitmoduleinterfaceflag } - local bmiflags = {} - local bmifiles = {} - for name, provide in pairs(m.provides) do - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - - local bmifile = provide.bmi - table.join2(args, { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile }) - table.insert(bmifiles, bmifile) - - batchcmds:add_depfiles(provide.sourcefile) - - table.join2(bmiflags, {modulefileflag .. bmifile}) - depmtime = math.max(depmtime, os.mtime(bmifile)) + 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!") + end end + local bmifile = provide.bmi + + local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } + 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:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, bmifiles, {"-c", "-o", objectfile})) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) + batchcmds:add_depfiles(provide.sourcefile) + + local bmiflags = modulefileflag .. bmifile target:add("cxxflags", bmiflags, {public = true, force = true}) target:add("objectfiles", objectfile) - for _, f in ipairs(bmiflags) do - target:data_add("cxx.modules.flags", f) - end + target:data_add("cxx.modules.flags", f) + depmtime = math.max(depmtime, os.mtime(bmifile)) end end batchcmds:set_depmtime(depmtime) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index ee4013d3e..0da739a7a 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -236,25 +236,32 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then - batchcmds:mkdir(path.directory(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!") + end + end + + local bmifile = provide.bmi + if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then + local args = {"-o", objectfile, "-c", provide.sourcefile}) - local args = {"-o", objectfile} - for name, provide in pairs(m.provides) do 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)) - local bmifile = provide.bmi - if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then - table.join2(args, {"-c", provide.sourcefile}) + batchcmds:add_depfiles(provide.sourcefile) + target:add("objectfiles", objectfile) - batchcmds:add_depfiles(provide.sourcefile) - end depmtime = math.max(depmtime, os.mtime(bmifile)) end - - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - - target:add("objectfiles", objectfile) 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 f3437eeab..96997b5b9 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -227,30 +227,34 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m then - batchcmds:mkdir(path.directory(objectfile)) - - local args = {"/c", "/Fo" .. objectfile} - local bmiflags = {} - for name, provide in pairs(m.provides) do - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - - local bmifile = provide.bmi - table.join2(args, {interfaceflag, ifcoutputflag, bmifile, provide.sourcefile}) - - batchcmds:add_depfiles(provide.sourcefile) - - table.join2(bmiflags, {referenceflag, name .. "=" .. path.filename(bmifile)}) - depmtime = math.max(depmtime, os.mtime(bmifile)) + 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!") + end end + local bmifile = provide.bmi + local args = {"/c", "/Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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, bmi_args), {envs = vcvars}) + batchcmds:add_depfiles(provide.sourcefile) + + local bmiflags = {referenceflag, name .. "=" .. path.filename(bmifile)} target:add("cxxflags", bmiflags, {force = true, expand = false}) for _, f in ipairs(bmiflags) do target:data_add("cxx.modules.flags", f) end target:add("objectfiles", objectfile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end end batchcmds:set_depmtime(depmtime) -- cgit v1.3.1 From 24c99b08df19fc7fdedd48e5745f7a86fb5b22b2 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 06:29:30 +0200 Subject: Fix syntax error --- xmake/rules/c++/modules/modules_support/gcc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 0da739a7a..449c901fd 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -251,7 +251,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local bmifile = provide.bmi if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then - local args = {"-o", objectfile, "-c", provide.sourcefile}) + local args = {"-o", objectfile, "-c", provide.sourcefile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) batchcmds:mkdir(path.directory(objectfile)) -- cgit v1.3.1 From 59bdca35cd89624f1706ece6fb9d3b448a491a86 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 06:30:01 +0200 Subject: Improve find angle header file --- xmake/rules/c++/modules/modules_support/common.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 8d3c8456d..564517ea1 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -310,7 +310,10 @@ end function find_angle_header_file(target, file) local headerpaths = modules_support(target).toolchain_includedirs(target) for _, dep in ipairs(target:orderdeps()) do - table.insert(headerpaths, dep:get("sysincludedirs") or dep:get("includedirs")) + local includedirs = dep:get("sysincludedirs") or dep:get("includedirs") + if includedirs then + table.join2(headerpaths, includedirs) + end end for _, pkg in ipairs(target:pkgs()) do local includedirs = pkg:get("sysincludedirs") or pkg:get("includedirs") -- cgit v1.3.1 From 24f8056d206e6b56bd71e87c1688bf68a45675d1 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 06:31:14 +0200 Subject: Fix clang output build module flags --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 734fa5a4d..4cefed14d 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -261,7 +261,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local bmiflags = modulefileflag .. bmifile target:add("cxxflags", bmiflags, {public = true, force = true}) target:add("objectfiles", objectfile) - target:data_add("cxx.modules.flags", f) + target:data_add("cxx.modules.flags", bmiflags) depmtime = math.max(depmtime, os.mtime(bmifile)) end end -- cgit v1.3.1 From a4f39242acb700b507c3fdd026e4fb77c4e13510 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 06:35:28 +0200 Subject: Fix find_angle_header_file pkgs discovery --- xmake/rules/c++/modules/modules_support/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 564517ea1..1be3b5170 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -315,7 +315,7 @@ function find_angle_header_file(target, file) table.join2(headerpaths, includedirs) end end - for _, pkg in ipairs(target:pkgs()) do + for _, pkg in pairs(target:pkgs()) do local includedirs = pkg:get("sysincludedirs") or pkg:get("includedirs") if includedirs then table.join2(headerpaths, includedirs) -- cgit v1.3.1 From a7e5b395286033c03d45b260713304ab04c7cc8a Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 08:27:09 +0200 Subject: Use common stl cache across targets --- xmake/rules/c++/modules/modules_support/common.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 1be3b5170..9c15cffbe 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -35,10 +35,7 @@ end -- get stl modules cache directory function stlmodules_cachedir(target) - local stlcachedir = path.join(target:autogendir(), "stlmodules", "cache") - if target:has_tool("cxx", "clang", "clangxx") then - stlcachedir = path.join(config.buildir(), "stlmodules", "cache") - end + local stlcachedir = path.join(config.buildir(), "stlmodules", "cache") if not os.isdir(stlcachedir) then os.mkdir(stlcachedir) end -- cgit v1.3.1 From 67568c5b063f00ed1131cf25f53bbb88d1e2db3b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Fri, 5 Aug 2022 08:27:26 +0200 Subject: Add C++23 and c* headers --- .../c++/modules/modules_support/stl_headers.lua | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/stl_headers.lua b/xmake/rules/c++/modules/modules_support/stl_headers.lua index aa5cb497c..849184ee5 100644 --- a/xmake/rules/c++/modules/modules_support/stl_headers.lua +++ b/xmake/rules/c++/modules/modules_support/stl_headers.lua @@ -102,7 +102,33 @@ function _stl_headers() "new", "type_traits", "string_view", - "stdexcept"} + "stdexcept", + "print", + "flat_map", + "flat_set", + "mdspan", + "stdfloat", + "generator", + "csetjmp", + "csignal", + "cstdarg", + "cstddef", + "cstdlib", + "cfloat", + "cinttypes", + "climits", + "cstdint", + "cassert", + "cerrno", + "cctype", + "cstring", + "cuchar", + "cwchar", + "cwctype", + "cfenv", + "cmath", + "clocale", + "cstdio"} end -- get all stl headers -- cgit v1.3.1 From 1579f0f9b0b0d255028212454a1242bfc6de4605 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:33:04 +0800 Subject: improve compile_commands --- xmake/plugins/project/clang/compile_commands.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 20b096a4c..15cbcfeb9 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -123,6 +123,25 @@ function _make_arguments(jsonfile, arguments, sourcefile) _g.firstline = false end +-- make commands for target +function _make_commands_for_targetrules(jsonfile, target, suffix) + for _, ruleinst in ipairs(target:orderules()) do + local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + if cmd.program then + _make_arguments(jsonfile, table.join(cmd.program, cmd.argv)) + end + end + end + end + end +end + -- make commands for object rules function _make_commands_for_objectrules(jsonfile, target, sourcebatch, suffix) @@ -181,11 +200,13 @@ end -- make objects function _make_objects(jsonfile, target, sourcebatch) + _make_commands_for_targetrules(jsonfile, target, "before") _make_commands_for_objectrules(jsonfile, target, sourcebatch, "before") if not _make_commands_for_objects(jsonfile, target, sourcebatch) then _make_commands_for_objectrules(jsonfile, target, sourcebatch) end _make_commands_for_objectrules(jsonfile, target, sourcebatch, "after") + _make_commands_for_targetrules(jsonfile, target, "after") end -- make target -- cgit v1.3.1 From 442ed69e3344e762a61698105154b9134d1d4496 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:36:52 +0800 Subject: support for compile_commands --- xmake/rules/c++/modules/modules_support/clang.lua | 2 -- xmake/rules/c++/modules/modules_support/common.lua | 2 +- xmake/rules/c++/modules/modules_support/gcc.lua | 5 +---- xmake/rules/c++/modules/modules_support/msvc.lua | 1 - xmake/rules/c++/modules/xmake.lua | 2 +- 5 files changed, 3 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 4cefed14d..19b42b135 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -249,13 +249,11 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end local bmifile = provide.bmi - local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } 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:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) - batchcmds:add_depfiles(provide.sourcefile) local bmiflags = modulefileflag .. bmifile diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 9c15cffbe..8805d51de 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -62,7 +62,6 @@ function get_headerunits(target, sourcebatch) for name, r in pairs(m.requires) do if r.method ~= "by-name" then local unittype = r.method == "include-angle" and ":angle" or ":quote" - if stl_headers.is_stl_header(name) then stl_headerunits = stl_headerunits or {} if not table.find_if(stl_headerunits, function(i, v) return v.name == name end) then @@ -405,3 +404,4 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) local jsondata = json.encode(output) io.writefile(jsonfile, jsondata) end + diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 449c901fd..00406787e 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -214,7 +214,6 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) if _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) then batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - batchcmds:add_depfiles(headerunit.path) end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -252,14 +251,12 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) local bmifile = provide.bmi if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then local args = {"-o", objectfile, "-c", 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) - target:add("objectfiles", objectfile) + target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 96997b5b9..7f9282de7 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -245,7 +245,6 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) 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, bmi_args), {envs = vcvars}) - batchcmds:add_depfiles(provide.sourcefile) local bmiflags = {referenceflag, name .. "=" .. path.filename(bmifile)} diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 4eae5f522..64f98bcab 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -51,7 +51,7 @@ rule("c++.build.modules") -- build dependencies rule("c++.build.modules.dependencies") - before_build(function(target, opt) + before_buildcmd(function(target, batchcmds, opt) if not target:data("cxx.has_modules") then return end -- cgit v1.3.1 From 9d29942180b6b623632ec133484f3c058937f3d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:41:51 +0800 Subject: remove unused opt --- xmake/rules/c++/modules/modules_support/clang.lua | 4 +++- xmake/rules/c++/modules/modules_support/common.lua | 6 +++--- xmake/rules/c++/modules/modules_support/gcc.lua | 4 +++- xmake/rules/c++/modules/modules_support/msvc.lua | 4 +++- xmake/rules/c++/modules/xmake.lua | 6 +++--- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 19b42b135..04f92bdeb 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -110,7 +110,9 @@ function generate_dependencies(target, sourcebatch, opt) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + if opt.progress then + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + end local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) if not os.isdir(outdir) then diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 8805d51de..88b9ab9fd 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -81,7 +81,7 @@ function get_headerunits(target, sourcebatch) end -- patch sourcebatch -function patch_sourcebatch(target, sourcebatch, opt) +function patch_sourcebatch(target, sourcebatch) local cachedir = modules_cachedir(target) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = {} @@ -135,7 +135,7 @@ function contains_modules(target) end -- load module infos -function load_moduleinfos(target, sourcebatch, opt) +function load_moduleinfos(target, sourcebatch) local moduleinfos for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) @@ -182,7 +182,7 @@ end } } }]] -function parse_dependency_data(target, moduleinfos, opt) +function parse_dependency_data(target, moduleinfos) local modules local cachedir = modules_cachedir(target) for _, moduleinfo in ipairs(moduleinfos) do diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 00406787e..841313a5b 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -126,7 +126,9 @@ function generate_dependencies(target, sourcebatch, opt) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + if opt.progress then + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + end local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) if not os.isdir(outdir) then diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7f9282de7..5e0fba4a9 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -89,7 +89,9 @@ function generate_dependencies(target, sourcebatch, opt) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function () - progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + if opt.progress then + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + end local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, projectdir))) if not os.isdir(outputdir) then os.mkdir(outputdir) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 64f98bcab..fcfcc18df 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -59,15 +59,15 @@ rule("c++.build.modules.dependencies") -- patch sourcebatch import("modules_support.common") local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] - common.patch_sourcebatch(target, sourcebatch, opt) + common.patch_sourcebatch(target, sourcebatch) -- generate dependencies local modules_support = common.modules_support(target) modules_support.generate_dependencies(target, sourcebatch, opt) -- load and parse module dependencies - local moduleinfos = common.load_moduleinfos(target, sourcebatch, opt) - local modules = common.parse_dependency_data(target, moduleinfos, opt) + local moduleinfos = common.load_moduleinfos(target, sourcebatch) + local modules = common.parse_dependency_data(target, moduleinfos) target:data_set("cxx.modules", modules) end) -- cgit v1.3.1 From bee2b91e6e7171c5034f2beef7bb6d0f1af247d8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:48:30 +0800 Subject: wrap generate deps --- xmake/rules/c++/modules/modules_support/common.lua | 14 ++++++++++++++ xmake/rules/c++/modules/xmake.lua | 20 ++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 88b9ab9fd..2cba5fe89 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -405,3 +405,17 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) io.writefile(jsonfile, jsondata) end +-- generate dependencies +function generate_dependencies(target, opt) + + -- get sourcebatch + local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] + patch_sourcebatch(target, sourcebatch) + + -- generate dependencies + modules_support(target).generate_dependencies(target, sourcebatch, opt) + + -- load and parse module dependencies + local moduleinfos = load_moduleinfos(target, sourcebatch) + return parse_dependency_data(target, moduleinfos) +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index fcfcc18df..d3dac2b69 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,23 +52,11 @@ rule("c++.build.modules") -- build dependencies rule("c++.build.modules.dependencies") before_buildcmd(function(target, batchcmds, opt) - if not target:data("cxx.has_modules") then - return + if target:data("cxx.has_modules") then + import("modules_support.common") + local modules = common.generate_dependencies(target, opt) + target:data_set("cxx.modules", modules) end - - -- patch sourcebatch - import("modules_support.common") - local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] - common.patch_sourcebatch(target, sourcebatch) - - -- generate dependencies - local modules_support = common.modules_support(target) - modules_support.generate_dependencies(target, sourcebatch, opt) - - -- load and parse module dependencies - local moduleinfos = common.load_moduleinfos(target, sourcebatch) - local modules = common.parse_dependency_data(target, moduleinfos) - target:data_set("cxx.modules", modules) end) -- build modules -- cgit v1.3.1 From 11c04bf269dba07285bbbc50dee6fa13cdc15f8d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:49:37 +0800 Subject: wrap generate headerunits --- xmake/rules/c++/modules/modules_support/common.lua | 30 +++++++++++++++------- xmake/rules/c++/modules/xmake.lua | 20 ++++----------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 2cba5fe89..b5a49e680 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -406,16 +406,28 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) end -- generate dependencies -function generate_dependencies(target, opt) - - -- get sourcebatch - local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] - patch_sourcebatch(target, sourcebatch) - - -- generate dependencies +function generate_dependencies(target, sourcebatch, opt) modules_support(target).generate_dependencies(target, sourcebatch, opt) - - -- load and parse module dependencies local moduleinfos = load_moduleinfos(target, sourcebatch) return parse_dependency_data(target, moduleinfos) end + +-- generate headerunits +function generate_headerunits(target, batchcmds, sourcebatch, opt) + + -- get headerunits info + local headerunits, stl_headerunits = get_headerunits(target, sourcebatch) + + -- generate headerunits + local headerunits_flags + -- build stl header units as other headerunits may need them + if stl_headerunits then + headerunits_flags = headerunits_flags or {} + table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits(target, batchcmds, stl_headerunits, opt)) + end + if headerunits then + headerunits_flags = headerunits_flags or {} + table.join2(headerunits_flags, modules_support(target).generate_user_headerunits(target, batchcmds, headerunits, opt)) + end + return headerunits_flags +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index d3dac2b69..321ee5089 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -54,7 +54,9 @@ rule("c++.build.modules.dependencies") before_buildcmd(function(target, batchcmds, opt) if target:data("cxx.has_modules") then import("modules_support.common") - local modules = common.generate_dependencies(target, opt) + local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] + common.patch_sourcebatch(target, sourcebatch) + local modules = common.generate_dependencies(target, sourcebatch, opt) target:data_set("cxx.modules", modules) end end) @@ -76,27 +78,15 @@ rule("c++.build.modules.builder") -- patch sourcebatch common.patch_sourcebatch(target, sourcebatch, opt) - -- get headerunits info - local headerunits, stl_headerunits = common.get_headerunits(target, sourcebatch) - -- generate headerunits - local headerunits_flags - local modules_support = common.modules_support(target) - -- build stl header units as other headerunits may need them - if stl_headerunits then - headerunits_flags = headerunits_flags or {} - table.join2(headerunits_flags, modules_support.generate_stl_headerunits(target, batchcmds, stl_headerunits, opt)) - end - if headerunits then - headerunits_flags = headerunits_flags or {} - table.join2(headerunits_flags, modules_support.generate_user_headerunits(target, batchcmds, headerunits, opt)) - end + local headerunits_flags = common.generate_headerunits(target, batchcmds, sourcebatch, opt) if headerunits_flags then target:add("cxxflags", headerunits_flags, {force = true, expand = false}) end -- topological sort local modules = target:data("cxx.modules") + local modules_support = common.modules_support(target) local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) modules_support.build_modules(target, batchcmds, objectfiles, modules, opt) end) -- cgit v1.3.1 From 8ac03c2d83d6cf5b9509ab2d4e756998711886b8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:50:07 +0800 Subject: remove unused import --- xmake/rules/c++/modules/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 321ee5089..a4288034d 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -73,7 +73,6 @@ rule("c++.build.modules.builder") end import("modules_support.common") - import("modules_support.stl_headers") -- patch sourcebatch common.patch_sourcebatch(target, sourcebatch, opt) -- cgit v1.3.1 From 53c31dfffd73cd635a6512d49b902e8c45dca102 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:59:10 +0800 Subject: add batchjobs stub --- xmake/rules/c++/modules/modules_support/clang.lua | 12 ++--- xmake/rules/c++/modules/modules_support/common.lua | 47 ++++++++++++++++--- xmake/rules/c++/modules/modules_support/gcc.lua | 12 ++--- xmake/rules/c++/modules/modules_support/msvc.lua | 12 ++--- xmake/rules/c++/modules/xmake.lua | 52 +++++++++++++--------- 5 files changed, 90 insertions(+), 45 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 04f92bdeb..89dbf4467 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -129,8 +129,8 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target stl header units -function generate_stl_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units for batchcmds +function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") -- get cachedirs @@ -159,8 +159,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) return flags end --- generate target user header units -function generate_user_headerunits(target, batchcmds, headerunits, opt) +-- generate target user header units for batchcmds +function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") @@ -212,8 +212,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) return flags end --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") -- get cachedirs diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index b5a49e680..5d5c625ec 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -52,10 +52,9 @@ function modules_cachedir(target) end -- get headerunits info -function get_headerunits(target, sourcebatch) +function get_headerunits(target, sourcebatch, modules) local headerunits local stl_headerunits - local modules = target:data("cxx.modules") for _, objectfile in ipairs(sourcebatch.objectfiles) do local m = modules[objectfile] if m then @@ -281,6 +280,7 @@ function _topological_sort_get_first_unmarked_node(nodes) end end +-- topological sort function sort_modules_by_dependencies(objectfiles, modules) local output = {} local nodes = {} @@ -412,22 +412,55 @@ function generate_dependencies(target, sourcebatch, opt) return parse_dependency_data(target, moduleinfos) end --- generate headerunits -function generate_headerunits(target, batchcmds, sourcebatch, opt) +-- generate headerunits for batchjobs, TODO +function generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) -- get headerunits info - local headerunits, stl_headerunits = get_headerunits(target, sourcebatch) + local headerunits, stl_headerunits = get_headerunits(target, sourcebatch, modules) -- generate headerunits + -- build stl header units as other headerunits may need them local headerunits_flags + if stl_headerunits then + headerunits_flags = headerunits_flags or {} +-- table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchjobs(target, batchjobs, stl_headerunits, opt)) + end + if headerunits then + headerunits_flags = headerunits_flags or {} +-- table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt)) + end + return headerunits_flags +end + +-- generate headerunits for batchcmds +function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + + -- get headerunits info + local headerunits, stl_headerunits = get_headerunits(target, sourcebatch, modules) + + -- generate headerunits -- build stl header units as other headerunits may need them + local headerunits_flags if stl_headerunits then headerunits_flags = headerunits_flags or {} - table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits(target, batchcmds, stl_headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchcmds(target, batchcmds, stl_headerunits, opt)) end if headerunits then headerunits_flags = headerunits_flags or {} - table.join2(headerunits_flags, modules_support(target).generate_user_headerunits(target, batchcmds, headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt)) end return headerunits_flags end + +-- build modules for batchjobs, TODO +function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) +-- modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) +end + +-- build modules for batchcmds +function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + modules_support(target).build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) +end + diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 841313a5b..08afba431 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -151,8 +151,8 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target stl header units -function generate_stl_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units for batchcmds +function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() @@ -175,8 +175,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) batchcmds:set_depmtime(depmtime) end --- generate target user header units -function generate_user_headerunits(target, batchcmds, headerunits, opt) +-- generate target user header units for batchcmds +function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() @@ -223,8 +223,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) batchcmds:set_depmtime(depmtime) end --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() local common_args = {"-x", "c++"} diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 5e0fba4a9..109c68751 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -111,8 +111,8 @@ function generate_dependencies(target, sourcebatch, opt) end end --- generate target stl header units -function generate_stl_headerunits(target, batchcmds, headerunits, opt) +-- generate target stl header units for batchcmds +function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -149,8 +149,8 @@ function generate_stl_headerunits(target, batchcmds, headerunits, opt) return flags end --- generate target user header units -function generate_user_headerunits(target, batchcmds, headerunits, opt) +-- generate target user header units for batchcmds +function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -203,8 +203,8 @@ function generate_user_headerunits(target, batchcmds, headerunits, opt) return flags end --- build module files -function build_modules(target, batchcmds, objectfiles, modules, opt) +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local cachedir = common.modules_cachedir(target) local compinst = target:compiler("cxx") diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index a4288034d..6d0da85c2 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -22,7 +22,6 @@ rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - add_deps("c++.build.modules.dependencies") add_deps("c++.build.modules.builder") add_deps("c++.build.modules.install") @@ -49,45 +48,58 @@ rule("c++.build.modules") end end) --- build dependencies -rule("c++.build.modules.dependencies") - before_buildcmd(function(target, batchcmds, opt) - if target:data("cxx.has_modules") then - import("modules_support.common") - local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] - common.patch_sourcebatch(target, sourcebatch) - local modules = common.generate_dependencies(target, sourcebatch, opt) - target:data_set("cxx.modules", modules) - end - end) - -- build modules rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) + -- TODO parallel build support to accelerate `xmake build` to build modules + --[[ + before_build_files(function(target, batchjobs, sourcebatch, opt) if not target:data("cxx.has_modules") then sourcebatch.objectfiles = {} return end + -- patch sourcebatch import("modules_support.common") + common.patch_sourcebatch(target, sourcebatch, opt) + + -- generate dependencies + local modules = common.generate_dependencies(target, sourcebatch, opt) + + -- generate headerunits + local headerunits_flags = common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + if headerunits_flags then + target:add("cxxflags", headerunits_flags, {force = true, expand = false}) + end + + -- build modules + common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + end, {batch = true})]] + + -- serial compilation only, usually used to support project generator + before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) + if not target:data("cxx.has_modules") then + sourcebatch.objectfiles = {} + return + end -- patch sourcebatch + import("modules_support.common") common.patch_sourcebatch(target, sourcebatch, opt) + -- generate dependencies + local modules = common.generate_dependencies(target, sourcebatch, opt) + -- generate headerunits - local headerunits_flags = common.generate_headerunits(target, batchcmds, sourcebatch, opt) + local headerunits_flags = common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) if headerunits_flags then target:add("cxxflags", headerunits_flags, {force = true, expand = false}) end - -- topological sort - local modules = target:data("cxx.modules") - local modules_support = common.modules_support(target) - local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) - modules_support.build_modules(target, batchcmds, objectfiles, modules, opt) + -- build modules + common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) end) -- install modules -- cgit v1.3.1 From b0379bcadce0b66fa5d3e5fc45d85a8ba365c92b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Aug 2022 00:10:00 +0800 Subject: cache module deps --- xmake/rules/c++/modules/modules_support/clang.lua | 3 +++ xmake/rules/c++/modules/modules_support/common.lua | 20 ++++++++++++++++---- xmake/rules/c++/modules/modules_support/gcc.lua | 3 +++ xmake/rules/c++/modules/modules_support/msvc.lua | 3 +++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 89dbf4467..18243fadf 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -106,6 +106,7 @@ end -- generate dependency files function generate_dependencies(target, sourcebatch, opt) + local changed = false local cachedir = common.modules_cachedir(target) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) @@ -122,11 +123,13 @@ function generate_dependencies(target, sourcebatch, opt) -- no support of p1689 atm local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) common.fallback_generate_dependencies(target, jsonfile, sourcefile) + changed = true local dependinfo = io.readfile(jsonfile) return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end + return changed end -- generate target stl header units for batchcmds diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 5d5c625ec..c91f52a9b 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -24,13 +24,19 @@ import("core.base.hashset") import("core.project.config") import("core.tool.compiler") import("core.cache.memcache", {alias = "_memcache"}) +import("core.cache.localcache", {alias = "_localcache"}) import("core.project.project") import("lib.detect.find_file") import("stl_headers") -- get memcache function memcache() - return _memcache.cache("rule.cxx.modules") + return _memcache.cache("cxxmodules") +end + +-- get localcache +function localcache() + return _localcache.cache("cxxmodules") end -- get stl modules cache directory @@ -407,9 +413,15 @@ end -- generate dependencies function generate_dependencies(target, sourcebatch, opt) - modules_support(target).generate_dependencies(target, sourcebatch, opt) - local moduleinfos = load_moduleinfos(target, sourcebatch) - return parse_dependency_data(target, moduleinfos) + local modules = localcache():get("modules") + local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) + if changed or modules == nil then + local moduleinfos = load_moduleinfos(target, sourcebatch) + modules = parse_dependency_data(target, moduleinfos) + localcache():set("modules", modules) + localcache():save() + end + return modules end -- generate headerunits for batchjobs, TODO diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 08afba431..cf996bdea 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -123,6 +123,7 @@ function generate_dependencies(target, sourcebatch, opt) local trtbdflag = get_trtbdflag(target) local depfileflag = get_depfileflag(target) local depoutputflag = get_depoutputflag(target) + local changed = false for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function() @@ -144,11 +145,13 @@ function generate_dependencies(target, sourcebatch, opt) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end + changed = true local dependinfo = io.readfile(jsonfile) return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end + return changed end -- generate target stl header units for batchcmds diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 109c68751..e261332c0 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -86,6 +86,7 @@ function generate_dependencies(target, sourcebatch, opt) local scandependenciesflag = get_scandependenciesflag(target) local common_args = {"/TP", scandependenciesflag} local cachedir = common.modules_cachedir(target) + local changed = false for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) depend.on_changed(function () @@ -104,11 +105,13 @@ function generate_dependencies(target, sourcebatch, opt) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) end + changed = true local dependinfo = io.readfile(jsonfile) return { moduleinfo = dependinfo } end, {dependfile = dependfile, files = {sourcefile}}) end + return changed end -- generate target stl header units for batchcmds -- cgit v1.3.1 From 57ac4f46f10e8525d4a5dec0e6c4c19f1ac35ab7 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 6 Aug 2022 06:24:34 +0200 Subject: Implement module mapper file for MSVC --- xmake/rules/c++/modules/modules_support/common.lua | 17 +++--- xmake/rules/c++/modules/modules_support/gcc.lua | 42 +++++++------- xmake/rules/c++/modules/modules_support/msvc.lua | 66 +++++++++++++--------- xmake/rules/c++/modules/xmake.lua | 5 +- 4 files changed, 71 insertions(+), 59 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index c91f52a9b..e5c8285b5 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -448,18 +448,19 @@ end function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- get headerunits info - local headerunits, stl_headerunits = get_headerunits(target, sourcebatch, modules) + local user_headerunits, stl_headerunits = get_headerunits(target, sourcebatch, modules) -- generate headerunits -- build stl header units as other headerunits may need them - local headerunits_flags - if stl_headerunits then - headerunits_flags = headerunits_flags or {} + if stl_headerunits or user_headerunits then + local headerunits_flags = localcache():get("headerunits_flags") + if stl_headerunits then + modules_support(target).generate_stl_headerunits_for_batchcmds(target, batchcmds, stl_headerunits, opt) table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchcmds(target, batchcmds, stl_headerunits, opt)) - end - if headerunits then - headerunits_flags = headerunits_flags or {} - table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt)) + end + if user_headerunits then + modules_support(target).generate_user_headerunits_for_batchcmds(target, batchcmds, user_headerunits, opt) + end end return headerunits_flags end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index cf996bdea..e99e83ae9 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -165,14 +165,14 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local projectdir = os.projectdir() local depmtime = 0 - for i, headerunit in ipairs(headerunits) do + for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then - local args = { "-c", "-x", "c++-system-header", headerunit.name } + local args = { "-c", "-x", "c++-system-header", headerunit.name } - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - end + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -216,11 +216,11 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) end - if _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) then - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - batchcmds:add_depfiles(headerunit.path) - end + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + batchcmds:add_depfiles(headerunit.path) + + _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -254,16 +254,16 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - if _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) then - local args = {"-o", objectfile, "-c", 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) - - target:add("objectfiles", objectfile) - depmtime = math.max(depmtime, os.mtime(bmifile)) - end + local args = {"-o", objectfile, "-c", 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)) 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 e261332c0..dc6739724 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -22,14 +22,41 @@ import("core.tool.compiler") import("core.project.project") import("core.project.depend") +import("core.project.config") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") +-- get and create the path of module mapper +function _get_module_mapper() + local mapper_file = path.join(config.buildir(), "mapper.txt") + if not os.isfile(mapper_file) then + io.writefile(mapper_file, "") + end + return mapper_file +end + +-- add a module or header unit into the mapper +-- +-- e.g +-- /headerUnit:angle cstdint=cstdint.ifc +-- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc +-- +function _add_module_to_mapper(file, argument, module) + for line in io.lines(file) do + if line:startswith(argument .. " " .. module) then + end + end + local f = io.open(file, "a") + f:print("%s %s", argument, module) + f:close() +end + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) + local mapper_file = _get_module_mapper() -- get flags local modulesflag = get_modulesflag(target) @@ -39,6 +66,7 @@ function load(target) target:add("cxxflags", modulesflag) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) target:add("cxxflags", {ifcsearchdirflag, stlcachedir}, {force = true, expand = false}) + target:add("cxxflags", "@" .. mapper_file, {force = true, expand = false}) -- add stdifcdir in case of if the user want to use Microsoft modularised STL local stdifcdirflag = get_stdifcdirflag(target) @@ -119,6 +147,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local mapper_file = _get_module_mapper() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -133,7 +162,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} - local flags = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -141,15 +169,12 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) - end - - local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()} - table.join2(flags, flag) + _add_module_to_mapper(mapper_file, headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()) + end depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- generate target user header units for batchcmds @@ -157,6 +182,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local mapper_file = _get_module_mapper() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -171,7 +197,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} - local flags = {} local projectdir = os.projectdir() local depmtime = 0 for _, headerunit in ipairs(headerunits) do @@ -191,24 +216,22 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:mkdir(path.directory(objectfile)) local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - batchcmds:add_depfiles(headerunit.path) + _add_module_to_mapper(mapper_file, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) - local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)} - table.join2(flags, flag) target:add("objectfiles", objectfile) - depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local cachedir = common.modules_cachedir(target) + local mapper_file = _get_module_mapper() local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") @@ -219,14 +242,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- append deps modules - for _, dep in ipairs(target:orderdeps()) do - local flags = dep:data("cxx.modules.flags") - if flags then - target:add("cxxflags", flags, {force = true, expand = false}) - end - end - -- build modules local common_args = {"/TP"} local depmtime = 0 @@ -247,20 +262,19 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local bmifile = provide.bmi local args = {"/c", "/Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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, bmi_args), {envs = vcvars}) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - local bmiflags = {referenceflag, name .. "=" .. path.filename(bmifile)} - target:add("cxxflags", bmiflags, {force = true, expand = false}) - for _, f in ipairs(bmiflags) do - target:data_add("cxx.modules.flags", f) - end + _add_module_to_mapper(mapper_file, referenceflag, name .. "=" .. path.filename(bmifile)) + target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end + batchcmds:set_depmtime(depmtime) end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 6d0da85c2..5676dcb10 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -93,10 +93,7 @@ rule("c++.build.modules.builder") local modules = common.generate_dependencies(target, sourcebatch, opt) -- generate headerunits - local headerunits_flags = common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - if headerunits_flags then - target:add("cxxflags", headerunits_flags, {force = true, expand = false}) - end + common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- build modules common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cgit v1.3.1 From dfbb0c6a93a76a1777682a485be3791a7cd6bd5c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 6 Aug 2022 23:49:02 +0200 Subject: Add missing C++ header and support experimental/ --- xmake/rules/c++/modules/modules_support/common.lua | 1 + xmake/rules/c++/modules/modules_support/msvc.lua | 2 +- xmake/rules/c++/modules/modules_support/stl_headers.lua | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index e5c8285b5..bd1603876 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -44,6 +44,7 @@ function stlmodules_cachedir(target) local stlcachedir = path.join(config.buildir(), "stlmodules", "cache") if not os.isdir(stlcachedir) then os.mkdir(stlcachedir) + os.mkdir(path.join(stlcachedir, "experimental")) end return stlcachedir end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index dc6739724..d0a5ec08b 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -170,7 +170,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) - _add_module_to_mapper(mapper_file, headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()) + _add_module_to_mapper(mapper_file, headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) end depmtime = math.max(depmtime, os.mtime(bmifile)) end diff --git a/xmake/rules/c++/modules/modules_support/stl_headers.lua b/xmake/rules/c++/modules/modules_support/stl_headers.lua index 849184ee5..599e2830c 100644 --- a/xmake/rules/c++/modules/modules_support/stl_headers.lua +++ b/xmake/rules/c++/modules/modules_support/stl_headers.lua @@ -103,6 +103,7 @@ function _stl_headers() "type_traits", "string_view", "stdexcept", + "condition_variable", "print", "flat_map", "flat_set", @@ -127,6 +128,7 @@ function _stl_headers() "cwctype", "cfenv", "cmath", + "ctime", "clocale", "cstdio"} end @@ -143,6 +145,9 @@ end -- is stl header? function is_stl_header(header) + if header:startswith("experimental/") then + header = header:sub(14, -1) + end return get_stl_headers():has(header) end -- cgit v1.3.1 From 2486a47e5997a5e3183e135a2ac86df4c83f5a30 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 6 Aug 2022 23:51:35 +0200 Subject: enable /stdifcsearchdir only if user ask for it --- xmake/rules/c++/modules/modules_support/msvc.lua | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index d0a5ec08b..af73f80af 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -69,17 +69,19 @@ function load(target) target:add("cxxflags", "@" .. mapper_file, {force = true, expand = false}) -- 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") - if vcvars.VCInstallDir and vcvars.VCToolsVersion then - local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") - if os.isdir(stdifcdir) then - target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false}) + if target:values("msvc.modules.stdifcdir") then + 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") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") + if os.isdir(stdifcdir) then + target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false}) + end end + break end - break end end -- cgit v1.3.1 From f085566ba853eb16c8658da1a38caa3a5e5728d3 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 6 Aug 2022 23:52:08 +0200 Subject: feed the linker with the header unit object files --- xmake/rules/c++/modules/modules_support/common.lua | 5 +- xmake/rules/c++/modules/modules_support/msvc.lua | 105 ++++++++++++++------- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index bd1603876..e32637abf 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -252,7 +252,6 @@ function _topological_sort_visit(node, nodes, modules, output) assert(not node.tempmarked) node.tempmarked = true local m1 = modules[node.objectfile] - assert(m1 and m1.provides) for _, n in ipairs(nodes) do if not n.tempmarked then local m2 = modules[n.objectfile] @@ -293,7 +292,7 @@ function sort_modules_by_dependencies(objectfiles, modules) local nodes = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] - if m and m.provides then + if m then table.insert(nodes, {marked = false, tempmarked = false, objectfile = objectfile}) end end @@ -457,13 +456,11 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu local headerunits_flags = localcache():get("headerunits_flags") if stl_headerunits then modules_support(target).generate_stl_headerunits_for_batchcmds(target, batchcmds, stl_headerunits, opt) - table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchcmds(target, batchcmds, stl_headerunits, opt)) end if user_headerunits then modules_support(target).generate_user_headerunits_for_batchcmds(target, batchcmds, user_headerunits, opt) end end - return headerunits_flags end -- build modules for batchjobs, TODO diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index af73f80af..b54767ee6 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -36,6 +36,15 @@ function _get_module_mapper() return mapper_file end +-- get and create the path of linker arguments +function _get_linker_argument_file() + local linker_file = path.join(config.buildir(), "linkargs.txt") + if not os.isfile(linker_file) then + io.writefile(linker_file, "") + end + return linker_file +end + -- add a module or header unit into the mapper -- -- e.g @@ -45,6 +54,7 @@ end function _add_module_to_mapper(file, argument, module) for line in io.lines(file) do if line:startswith(argument .. " " .. module) then + return end end local f = io.open(file, "a") @@ -52,11 +62,28 @@ function _add_module_to_mapper(file, argument, module) f:close() end +-- add an objectfile to the linker args +-- +-- e.g +-- foo.obj +-- +function _add_objectfile_to_link_arguments(file, objectfile) + for line in io.lines(file) do + if line:startswith(objectfile) then + return + end + end + local f = io.open(file, "a") + f:print(objectfile) + f:close() +end + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) local mapper_file = _get_module_mapper() + local linker_file = _get_linker_argument_file() -- get flags local modulesflag = get_modulesflag(target) @@ -66,9 +93,15 @@ function load(target) target:add("cxxflags", modulesflag) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) target:add("cxxflags", {ifcsearchdirflag, stlcachedir}, {force = true, expand = false}) - target:add("cxxflags", "@" .. mapper_file, {force = true, expand = false}) + target:add("cxxflags", {ifcsearchdirflag, path.join(stlcachedir, "experimental")}, {force = true, expand = false}) + target:add("cxxflags", "@" .. mapper_file, {force = true}) + + local linker_file_flag = "@".. linker_file + target:add("ldflags", linker_file_flag, {force = true}) + target:add("arflags", linker_file_flag, {force = true}) + target:add("shflags", linker_file_flag, {force = true}) - -- add stdifcdir in case of if the user want to use Microsoft modularised STL + -- add stdifcdir in case of if the user ask for it if target:values("msvc.modules.stdifcdir") then local stdifcdirflag = get_stdifcdirflag(target) for _, toolchain_inst in ipairs(target:toolchains()) do @@ -114,7 +147,7 @@ function generate_dependencies(target, sourcebatch, opt) local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") local scandependenciesflag = get_scandependenciesflag(target) - local common_args = {"/TP", scandependenciesflag} + local common_args = {"-TP", scandependenciesflag} local cachedir = common.modules_cachedir(target) local changed = false for _, sourcefile in ipairs(sourcebatch.sourcefiles) do @@ -130,7 +163,7 @@ function generate_dependencies(target, sourcebatch, opt) local jsonfile = path.join(outputdir, path.filename(sourcefile) .. ".json") if scandependenciesflag then - local args = {jsonfile, sourcefile, "/Fo" .. target:objectfile(sourcefile)} + local args = {jsonfile, sourcefile, "-Fo" .. target:objectfile(sourcefile)} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else common.fallback_generate_dependencies(target, jsonfile, sourcefile) @@ -150,6 +183,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") local mapper_file = _get_module_mapper() + local linker_file = _get_linker_argument_file() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -162,17 +196,19 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local stlcachedir = common.stlmodules_cachedir(target) -- build headerunits - local common_args = {"/TP", exportheaderflag, "/c"} + local common_args = {"-TP", exportheaderflag, "-c"} local objectfiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if not os.isfile(bmifile) then - local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir} + local objectfile = bmifile .. ".obj" + if not os.isfile(bmifile) or not os.isfile(objectfile) then + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args), {envs = vcvars}) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) _add_module_to_mapper(mapper_file, headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) + _add_objectfile_to_link_arguments(linker_file, objectfile) end depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -185,6 +221,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") local mapper_file = _get_module_mapper() + local linker_file = _get_linker_argument_file() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -197,7 +234,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local cachedir = common.modules_cachedir(target) -- build headerunits - local common_args = {"/TP", exportheaderflag, "/c"} + local common_args = {"-TP", exportheaderflag, "-c"} local objectfiles = {} local projectdir = os.projectdir() local depmtime = 0 @@ -223,8 +260,8 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) _add_module_to_mapper(mapper_file, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) + _add_objectfile_to_link_arguments(linker_file, objectfile) - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -245,7 +282,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local referenceflag = get_referenceflag(target) -- build modules - local common_args = {"/TP"} + local common_args = {"-TP"} local depmtime = 0 for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -263,7 +300,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - local args = {"/c", "/Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) batchcmds:mkdir(path.directory(objectfile)) @@ -288,8 +325,8 @@ 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" + 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 @@ -301,8 +338,8 @@ 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" + 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 @@ -314,8 +351,8 @@ 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" + 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 @@ -327,8 +364,8 @@ 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" + 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 @@ -340,8 +377,8 @@ 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" + 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 @@ -353,9 +390,9 @@ 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" + 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 @@ -366,9 +403,9 @@ 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" + 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 @@ -380,8 +417,8 @@ function get_exportheaderflag(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" + if compinst:has_flags(modulesflag .. " -exportHeader", "cxxflags", {flagskey = "cl_export_header"}) then + exportheaderflag = "-exportHeader" end _g.exportheaderflag = exportheaderflag or false end @@ -392,8 +429,8 @@ 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" + if compinst:has_flags("-stdIfcDir", "cxxflags", {flagskey = "cl_std_ifc_dir"}) then + stdifcdirflag = "-stdIfcDir" end _g.stdifcdirflag = stdifcdirflag or false end @@ -405,7 +442,7 @@ function get_scandependenciesflag(target) 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", + 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 @@ -415,7 +452,7 @@ function get_scandependenciesflag(target) end return ok, errors end}) then - scandependenciesflag = "/scanDependencies" + scandependenciesflag = "-scanDependencies" end _g.scandependenciesflag = scandependenciesflag or false end -- cgit v1.3.1 From c39a7060382929321332cf4fc3c00efa533ea758 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 02:36:46 +0200 Subject: Use target:add("xxflags") instead of passing a file --- xmake/rules/c++/modules/modules_support/common.lua | 3 +++ xmake/rules/c++/modules/modules_support/msvc.lua | 25 ++++++++++++++++------ xmake/rules/c++/modules/xmake.lua | 5 +++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index e32637abf..aa1db3f0f 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -475,3 +475,6 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op modules_support(target).build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) end +function append_headerunits_objectfiles(target) + modules_support(target).append_headerunits_objectfiles(target) +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b54767ee6..1d946d339 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -94,12 +94,6 @@ function load(target) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) target:add("cxxflags", {ifcsearchdirflag, stlcachedir}, {force = true, expand = false}) target:add("cxxflags", {ifcsearchdirflag, path.join(stlcachedir, "experimental")}, {force = true, expand = false}) - target:add("cxxflags", "@" .. mapper_file, {force = true}) - - local linker_file_flag = "@".. linker_file - target:add("ldflags", linker_file_flag, {force = true}) - target:add("arflags", linker_file_flag, {force = true}) - target:add("shflags", linker_file_flag, {force = true}) -- add stdifcdir in case of if the user ask for it if target:values("msvc.modules.stdifcdir") then @@ -281,6 +275,11 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) + -- add + for line in io.lines(mapper_file) do + target:add("cxxflags", line, {force = true}) + end + -- build modules local common_args = {"-TP"} local depmtime = 0 @@ -458,3 +457,17 @@ function get_scandependenciesflag(target) end return scandependenciesflag or nil end + +function append_headerunits_objectfiles(target) + local linker_file = _get_linker_argument_file() + + for line in io.lines(linker_file) do + if target:kind() == "binary" then + target:add("ldflags", line, {force = true}) + elseif target:kind() == "static" then + target:add("arflags", line, {force = true}) + elseif target:kind() == "shared" then + target:add("shflags", line, {force = true}) + end + end +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 5676dcb10..4117004cc 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -99,6 +99,11 @@ rule("c++.build.modules.builder") common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) end) + before_link(function(target) + import("modules_support.common") + common.append_headerunits_objectfiles(target) + end) + -- install modules rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- cgit v1.3.1 From c3adbbb8bf99185329511029b09483df2308eb59 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 03:44:04 +0200 Subject: Code cleanup --- xmake/rules/c++/modules/modules_support/msvc.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 1d946d339..e61beb6f2 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -191,7 +191,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} - local objectfiles = {} local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -229,7 +228,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} - local objectfiles = {} local projectdir = os.projectdir() local depmtime = 0 for _, headerunit in ipairs(headerunits) do @@ -275,7 +273,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- add + -- append module mapper flags for line in io.lines(mapper_file) do target:add("cxxflags", line, {force = true}) end @@ -458,6 +456,7 @@ function get_scandependenciesflag(target) return scandependenciesflag or nil end +-- append .obj to final link function append_headerunits_objectfiles(target) local linker_file = _get_linker_argument_file() -- cgit v1.3.1 From 823ea42a24ad71abc284c118e1534b5d229c5a5b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 03:44:36 +0200 Subject: Build stl header units only when not present and add dummy append_headerunits_objectfiles function --- xmake/rules/c++/modules/modules_support/gcc.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e99e83ae9..7f3d94dc9 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -167,10 +167,11 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - local args = { "-c", "-x", "c++-system-header", headerunit.name } - - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + if not os.isfile(bmifile) then + local args = { "-c", "-x", "c++-system-header", headerunit.name } + batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -334,3 +335,7 @@ function get_depoutputflag(target) end return depoutputflag or nil end + +-- no .o generated by header units on GCC +function append_headerunits_objectfiles(target) +end \ No newline at end of file -- cgit v1.3.1 From f079c8e059ead5aeef0400ef360b6201150e1478 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 04:10:32 +0200 Subject: Implement module mapper for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 130 +++++++++++++++------- xmake/rules/c++/modules/modules_support/msvc.lua | 8 +- 2 files changed, 96 insertions(+), 42 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 18243fadf..b50fd4bf2 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -27,31 +27,56 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") +-- get and create the path of module mapper +function _get_module_mapper() + local mapper_file = path.join(config.buildir(), "mapper.txt") + if not os.isfile(mapper_file) then + io.writefile(mapper_file, "") + end + return mapper_file +end + +-- add a module or header unit into the mapper +-- +-- e.g +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc +-- +function _add_module_to_mapper(target, file, module, bmi) + local modulefileflag = get_modulefileflag(target) + for line in io.lines(file) do + if line:startswith(modulefileflag .. module) then + return + end + end + local f = io.open(file, "a") + f:print("%s%s=%s", modulefileflag, module, bmi) + f:close() +end + + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) + local mapper_file = _get_module_mapper() -- get module and module cache flags local modulesflag = get_modulesflag(target) + local builtinmodulemapflag = get_builtinmodulemapflag(target) local implicitmodulesflag = get_implicitmodulesflag(target) - local implicitmodulemapsflag = get_implicitmodulemapsflag(target) - local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) + local noimplicitmodulemapsflag = get_noimplicitmodulemapsflag(target) -- add module flags target:add("cxxflags", modulesflag) -- add the module cache directory + target:add("cxxflags", builtinmodulemapflag, {force = true}) target:add("cxxflags", implicitmodulesflag, {force = true}) - target:add("cxxflags", implicitmodulemapsflag, {force = true}) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) - - -- add module cachedirs of all dependent targets with modules - -- this target maybe does not contain module files, @see https://github.com/xmake-io/xmake/issues/1858 - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.modules_cachedir(dep) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) - end + target:add("cxxflags", noimplicitmodulemapsflag, {force = true}) + -- target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + + target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++")) end -- get includedirs for stl headers @@ -135,6 +160,7 @@ end -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) @@ -145,7 +171,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local projectdir = os.projectdir() - local flags = {} local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -153,19 +178,22 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - end - table.insert(flags, modulefileflag .. bmifile) + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) + end + end depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -205,19 +233,18 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - batchcmds:add_depfiles(headerunit.path) + _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) - table.insert(flags, modulefileflag .. bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -225,14 +252,10 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - local modulefileflag = get_modulefileflag(target) - -- append deps modules - for _, dep in ipairs(target:orderdeps()) do - local flags = dep:data("cxx.modules.flags") - if flags then - target:add("cxxflags", flags, {force = true, expand = false}) - end + -- append module mapper flags + for line in io.lines(mapper_file) do + target:add("cxxflags", line, {force = true}) end -- build modules @@ -261,10 +284,9 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - local bmiflags = modulefileflag .. bmifile - target:add("cxxflags", bmiflags, {public = true, force = true}) + _add_module_to_mapper(target, mapper_file, name, bmifile) + target:add("objectfiles", objectfile) - target:data_add("cxx.modules.flags", bmiflags) depmtime = math.max(depmtime, os.mtime(bmifile)) end end @@ -293,6 +315,34 @@ function get_modulesflag(target) return modulesflag or nil end +function get_builtinmodulemapflag(target) + local builtinmodulemapflag = _g.builtinmodulemapflag + if builtinmodulemapflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fbuiltin-module-map", "cxxflags", {flagskey = "clang_builtin_module_map"}) then + builtinmodulemapflag = "-fbuiltin-module-map" + end + assert(builtinmodulemapflag, "compiler(clang): does not support c++ module!") + _g.builtinmodulemapflag = builtinmodulemapflag or false + end + return builtinmodulemapflag or nil +end + +function get_modulemapfileflag(target) + local modulemapfileflag = _g.modulemapfileflag + if modulemapfileflag == nil then + local compinst = target:compiler("cxx") + local mapper_file = path.join(os.tmpdir(), "mapper.txt") + os.touch(mapper_file) + if compinst:has_flags("-fmodule-map-file=" .. mapper_file, "cxxflags", {flagskey = "clang_module_map_file"}) then + modulemapfileflag = "-fmodule-map-file=" + end + assert(modulemapfileflag, "compiler(clang): does not support c++ module!") + _g.modulemapfileflag = modulemapfileflag or false + end + return modulemapfileflag or nil +end + function get_implicitmodulesflag(target) local implicitmodulesflag = _g.implicitmodulesflag if implicitmodulesflag == nil then @@ -306,17 +356,17 @@ function get_implicitmodulesflag(target) return implicitmodulesflag or nil end -function get_implicitmodulemapsflag(target) - local implicitmodulemapsflag = _g.implicitmodulemapsflag - if implicitmodulemapsflag == nil then +function get_noimplicitmodulemapsflag(target) + local noimplicitmodulemapsflag = _g.noimplicitmodulemapsflag + if noimplicitmodulemapsflag == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-fimplicit-module-maps", "cxxflags", {flagskey = "clang_implicit_module_maps"}) then - implicitmodulemapsflag = "-fimplicit-module-maps" + if compinst:has_flags("-fno-implicit-module-maps", "cxxflags", {flagskey = "clang_no_implicit_module_maps"}) then + noimplicitmodulemapsflag = "-fno-implicit-module-maps" end - assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") - _g.implicitmodulemapsflag = implicitmodulemapsflag or false + assert(noimplicitmodulemapsflag, "compiler(clang): does not support c++ module!") + _g.noimplicitmodulemapsflag = noimplicitmodulemapsflag or false end - return implicitmodulemapsflag or nil + return noimplicitmodulemapsflag or nil end function get_prebuiltmodulepathflag(target) @@ -388,11 +438,15 @@ function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then + if compinst:has_flags(get_modulesflag(target) .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags(get_modulesflag(target) .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false end return support_headerunits or nil end + +-- no .o generated by header units on Clang +function append_headerunits_objectfiles(target) +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index e61beb6f2..1728d59f1 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -261,17 +261,17 @@ end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.modules_cachedir(target) - local mapper_file = _get_module_mapper() - local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + -- get cachedirs + local cachedir = common.modules_cachedir(target) + -- get flags local ifcoutputflag = get_ifcoutputflag(target) local interfaceflag = get_interfaceflag(target) - local referenceflag = get_referenceflag(target) -- append module mapper flags for line in io.lines(mapper_file) do -- cgit v1.3.1 From dffff05e4c8048e4fb379275382493dcf35483c4 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 05:40:30 +0200 Subject: Fix header unit path in module mapper --- xmake/rules/c++/modules/modules_support/clang.lua | 25 ++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index b50fd4bf2..00d110a5e 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -36,11 +36,10 @@ function _get_module_mapper() return mapper_file end --- add a module or header unit into the mapper +-- add a module into the mapper -- -- e.g -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc --- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc -- function _add_module_to_mapper(target, file, module, bmi) local modulefileflag = get_modulefileflag(target) @@ -54,6 +53,22 @@ function _add_module_to_mapper(target, file, module, bmi) f:close() end +-- add a header unit into the mapper +-- +-- e.g +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.ifc +-- +function _add_headerunit_to_mapper(target, file, bmi) + local modulefileflag = get_modulefileflag(target) + for line in io.lines(file) do + if line:startswith(modulefileflag .. bmi) then + return + end + end + local f = io.open(file, "a") + f:print("%s%s", modulefileflag, bmi) + f:close() +end -- load module support for the current target function load(target) @@ -175,13 +190,13 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then - local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) + _add_headerunit_to_mapper(target, mapper_file, bmifile) end end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -234,7 +249,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) + _add_headerunit_to_mapper(target, mapper_file, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end -- cgit v1.3.1 From b4fa2913604afba00cc09572340ce44389fb5151 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 12:41:58 +0200 Subject: Improve code --- xmake/rules/c++/modules/modules_support/msvc.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 1728d59f1..7bb9c97b5 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -459,13 +459,12 @@ end -- append .obj to final link function append_headerunits_objectfiles(target) local linker_file = _get_linker_argument_file() - for line in io.lines(linker_file) do - if target:kind() == "binary" then + if target:is_binary() then target:add("ldflags", line, {force = true}) - elseif target:kind() == "static" then + elseif target:is_static() == "static" then target:add("arflags", line, {force = true}) - elseif target:kind() == "shared" then + elseif target:is_shared() == "shared" then target:add("shflags", line, {force = true}) end end -- cgit v1.3.1 From 2b5a9618fd478e9e579a3b64405dd0c9eba63a7d Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 12:42:05 +0200 Subject: Fix comments --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 00d110a5e..d1aebdd88 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -39,7 +39,7 @@ end -- add a module into the mapper -- -- e.g --- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- function _add_module_to_mapper(target, file, module, bmi) local modulefileflag = get_modulefileflag(target) @@ -56,7 +56,7 @@ end -- add a header unit into the mapper -- -- e.g --- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.ifc +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- function _add_headerunit_to_mapper(target, file, bmi) local modulefileflag = get_modulefileflag(target) -- cgit v1.3.1 From 31d14e3a11f9da2399939ab7e22a973c22dab227 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 13:09:17 +0200 Subject: Improve code --- xmake/rules/c++/modules/modules_support/clang.lua | 3 +-- xmake/rules/c++/modules/modules_support/gcc.lua | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index d1aebdd88..28ee152bc 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -89,7 +89,6 @@ function load(target) target:add("cxxflags", builtinmodulemapflag, {force = true}) target:add("cxxflags", implicitmodulesflag, {force = true}) target:add("cxxflags", noimplicitmodulemapsflag, {force = true}) - -- target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++")) end @@ -347,7 +346,7 @@ function get_modulemapfileflag(target) local modulemapfileflag = _g.modulemapfileflag if modulemapfileflag == nil then local compinst = target:compiler("cxx") - local mapper_file = path.join(os.tmpdir(), "mapper.txt") + local mapper_file = path.join(os.tmpfile(), "mapper.txt") os.touch(mapper_file) if compinst:has_flags("-fmodule-map-file=" .. mapper_file, "cxxflags", {flagskey = "clang_module_map_file"}) then modulemapfileflag = "-fmodule-map-file=" diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 7f3d94dc9..e5deed0cd 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -173,6 +173,8 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end + batchcmds:add_depfiles(headerunit.path) + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) end -- cgit v1.3.1 From 7c68491b43bb32683731473cbf77d1923ad14e0e Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 13:12:22 +0200 Subject: Fix msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7bb9c97b5..dbdfbf744 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -272,6 +272,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- get flags local ifcoutputflag = get_ifcoutputflag(target) local interfaceflag = get_interfaceflag(target) + local referenceflag = get_referenceflag(target) -- append module mapper flags for line in io.lines(mapper_file) do -- cgit v1.3.1 From a8f09abe90cf7955a0b8bb2f6747ecc6ac0c28a7 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 13:38:47 +0200 Subject: Improve code --- xmake/rules/c++/modules/modules_support/msvc.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index dbdfbf744..371cc1f50 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -199,8 +199,9 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(mapper_file, headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) + _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) _add_objectfile_to_link_arguments(linker_file, objectfile) end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -251,7 +252,8 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(mapper_file, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) + + _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) _add_objectfile_to_link_arguments(linker_file, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) -- cgit v1.3.1 From 1c96d8379173130442227222c75e0caac6afb40b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 14:59:23 +0200 Subject: Use localcache instead of a file --- xmake/rules/c++/modules/modules_support/clang.lua | 52 ++++++-------- xmake/rules/c++/modules/modules_support/common.lua | 9 ++- xmake/rules/c++/modules/modules_support/gcc.lua | 4 -- xmake/rules/c++/modules/modules_support/msvc.lua | 81 ++++++---------------- 4 files changed, 51 insertions(+), 95 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 28ee152bc..4749f7fe3 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -27,30 +27,21 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") --- get and create the path of module mapper -function _get_module_mapper() - local mapper_file = path.join(config.buildir(), "mapper.txt") - if not os.isfile(mapper_file) then - io.writefile(mapper_file, "") - end - return mapper_file -end - -- add a module into the mapper -- -- e.g -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- -function _add_module_to_mapper(target, file, module, bmi) +function _add_module_to_mapper(target, module, bmi) + local cache = common.localcache():get("mapflags") or {} local modulefileflag = get_modulefileflag(target) - for line in io.lines(file) do - if line:startswith(modulefileflag .. module) then - return - end + local mapflag = format("%s%s=%s", modulefileflag, module, bmi) + if table.contains(cache, mapflag) then + return end - local f = io.open(file, "a") - f:print("%s%s=%s", modulefileflag, module, bmi) - f:close() + table.insert(cache, mapflag) + common.localcache():set("mapflags", cache) + common.localcache():save("mapflags") end -- add a header unit into the mapper @@ -58,7 +49,18 @@ end -- e.g -- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- -function _add_headerunit_to_mapper(target, file, bmi) +function _add_headerunit_to_mapper(target, bmi) + local cache = common.localcache():get("mapflags") or {} + local modulefileflag = get_modulefileflag(target) + local mapflag = format("%s%s", modulefileflag, bmi) + if table.contains(cache, mapflag) then + return + end + table.insert(cache, mapflag) + common.localcache():set("mapflags", cache) + common.localcache():save("mapflags") +end + local modulefileflag = get_modulefileflag(target) for line in io.lines(file) do if line:startswith(modulefileflag .. bmi) then @@ -74,7 +76,6 @@ end function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) - local mapper_file = _get_module_mapper() -- get module and module cache flags local modulesflag = get_modulesflag(target) @@ -174,7 +175,6 @@ end -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") - local mapper_file = _get_module_mapper() -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) @@ -195,7 +195,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, mapper_file, bmifile) + _add_headerunit_to_mapper(target, bmifile) end end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -207,7 +207,6 @@ end function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") - local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -248,7 +247,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - _add_headerunit_to_mapper(target, mapper_file, bmifile) + _add_headerunit_to_mapper(target, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -258,7 +257,6 @@ end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") - local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -298,7 +296,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(target, mapper_file, name, bmifile) + _add_module_to_mapper(target, name, bmifile) target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -459,8 +457,4 @@ function has_headerunitsupport(target) _g.support_headerunits = support_headerunits or false end return support_headerunits or nil -end - --- no .o generated by header units on Clang -function append_headerunits_objectfiles(target) end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index aa1db3f0f..34d014238 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -476,5 +476,12 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op end function append_headerunits_objectfiles(target) - modules_support(target).append_headerunits_objectfiles(target) + local cache = localcache():get("headerunit_objectfiles") or {} + if target:is_binary() then + target:add("ldflags", cache, {force = true}) + elseif target:is_static() == "static" then + target:add("arflags", cache, {force = true}) + elseif target:is_shared() == "shared" then + target:add("shflags", cache, {force = true}) + end end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e5deed0cd..99045cf54 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -336,8 +336,4 @@ function get_depoutputflag(target) _g.depoutputflag = depoutputflag or false end return depoutputflag or nil -end - --- no .o generated by header units on GCC -function append_headerunits_objectfiles(target) end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 371cc1f50..b2b2e605a 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -27,39 +27,21 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") --- get and create the path of module mapper -function _get_module_mapper() - local mapper_file = path.join(config.buildir(), "mapper.txt") - if not os.isfile(mapper_file) then - io.writefile(mapper_file, "") - end - return mapper_file -end - --- get and create the path of linker arguments -function _get_linker_argument_file() - local linker_file = path.join(config.buildir(), "linkargs.txt") - if not os.isfile(linker_file) then - io.writefile(linker_file, "") - end - return linker_file -end - -- add a module or header unit into the mapper -- -- e.g -- /headerUnit:angle cstdint=cstdint.ifc -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- -function _add_module_to_mapper(file, argument, module) - for line in io.lines(file) do - if line:startswith(argument .. " " .. module) then - return - end +function _add_module_to_mapper(argument, module) + local cache = common.localcache():get("mapflags") or {} + local mapflag = format("%s %s", argument, module) + if table.contains(cache, mapflag) then + return end - local f = io.open(file, "a") - f:print("%s %s", argument, module) - f:close() + table.insert(cache, mapflag) + common.localcache():set("mapflags", cache) + common.localcache():save("mapflags") end -- add an objectfile to the linker args @@ -67,23 +49,20 @@ end -- e.g -- foo.obj -- -function _add_objectfile_to_link_arguments(file, objectfile) - for line in io.lines(file) do - if line:startswith(objectfile) then - return - end +function _add_objectfile_to_link_arguments(objectfile) + local cache = common.localcache():get("headerunit_objectfiles") or {} + if table.contains(cache, objectfile) then + return end - local f = io.open(file, "a") - f:print(objectfile) - f:close() + table.insert(cache, objectfile) + common.localcache():set("headerunit_objectfiles", cache) + common.localcache():save("headerunit_objectfiles") end -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) - local mapper_file = _get_module_mapper() - local linker_file = _get_linker_argument_file() -- get flags local modulesflag = get_modulesflag(target) @@ -176,8 +155,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - local mapper_file = _get_module_mapper() - local linker_file = _get_linker_argument_file() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -202,7 +179,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:add_depfiles(headerunit.path) _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) - _add_objectfile_to_link_arguments(linker_file, objectfile) + _add_objectfile_to_link_arguments(objectfile) end depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -214,8 +191,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - local mapper_file = _get_module_mapper() - local linker_file = _get_linker_argument_file() -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -254,7 +229,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:add_depfiles(headerunit.path) _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) - _add_objectfile_to_link_arguments(linker_file, objectfile) + _add_objectfile_to_link_arguments(objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -264,7 +239,6 @@ end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") - local mapper_file = _get_module_mapper() local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") @@ -277,9 +251,8 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local referenceflag = get_referenceflag(target) -- append module mapper flags - for line in io.lines(mapper_file) do - target:add("cxxflags", line, {force = true}) - end + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) -- build modules local common_args = {"-TP"} @@ -307,7 +280,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(mapper_file, referenceflag, name .. "=" .. path.filename(bmifile)) + _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -457,18 +430,4 @@ function get_scandependenciesflag(target) _g.scandependenciesflag = scandependenciesflag or false end return scandependenciesflag or nil -end - --- append .obj to final link -function append_headerunits_objectfiles(target) - local linker_file = _get_linker_argument_file() - for line in io.lines(linker_file) do - if target:is_binary() then - target:add("ldflags", line, {force = true}) - elseif target:is_static() == "static" then - target:add("arflags", line, {force = true}) - elseif target:is_shared() == "shared" then - target:add("shflags", line, {force = true}) - end - end end \ No newline at end of file -- cgit v1.3.1 From d32859aa18fe79e2876bdb793956c15e0479aaee Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Aug 2022 23:59:48 +0800 Subject: add some tests for cppmodules --- tests/projects/c++/modules/class/test.lua | 20 ++++++++++++++++++++ .../c++/modules/cpp_with_moduledeps/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/dependence/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/dependence2/test.lua | 20 ++++++++++++++++++++ .../projects/c++/modules/hello with spaces/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/hello/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/impl_unit/test.lua | 20 ++++++++++++++++++++ .../c++/modules/inline_and_template/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/staticlib/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/submodules/test.lua | 20 ++++++++++++++++++++ tests/projects/c++/modules/submodules2/test.lua | 20 ++++++++++++++++++++ 11 files changed, 220 insertions(+) create mode 100644 tests/projects/c++/modules/class/test.lua create mode 100644 tests/projects/c++/modules/cpp_with_moduledeps/test.lua create mode 100644 tests/projects/c++/modules/dependence/test.lua create mode 100644 tests/projects/c++/modules/dependence2/test.lua create mode 100644 tests/projects/c++/modules/hello with spaces/test.lua create mode 100644 tests/projects/c++/modules/hello/test.lua create mode 100644 tests/projects/c++/modules/impl_unit/test.lua create mode 100644 tests/projects/c++/modules/inline_and_template/test.lua create mode 100644 tests/projects/c++/modules/staticlib/test.lua create mode 100644 tests/projects/c++/modules/submodules/test.lua create mode 100644 tests/projects/c++/modules/submodules2/test.lua diff --git a/tests/projects/c++/modules/class/test.lua b/tests/projects/c++/modules/class/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/class/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/test.lua b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/dependence/test.lua b/tests/projects/c++/modules/dependence/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/dependence/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/dependence2/test.lua b/tests/projects/c++/modules/dependence2/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/dependence2/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/hello with spaces/test.lua b/tests/projects/c++/modules/hello with spaces/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/hello with spaces/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/hello/test.lua b/tests/projects/c++/modules/hello/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/hello/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/impl_unit/test.lua b/tests/projects/c++/modules/impl_unit/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/impl_unit/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/inline_and_template/test.lua b/tests/projects/c++/modules/inline_and_template/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/inline_and_template/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/staticlib/test.lua b/tests/projects/c++/modules/staticlib/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/staticlib/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/submodules/test.lua b/tests/projects/c++/modules/submodules/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/submodules/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end diff --git a/tests/projects/c++/modules/submodules2/test.lua b/tests/projects/c++/modules/submodules2/test.lua new file mode 100644 index 000000000..76b141d6b --- /dev/null +++ b/tests/projects/c++/modules/submodules2/test.lua @@ -0,0 +1,20 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + local test = false + if is_subhost("windows") then + test = true + elseif is_host("linux", "macosx") then + local gcc = find_tool("gcc", {version = true}) + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + test = true + elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + end + if test then + os.exec("xmake") + end +end -- cgit v1.3.1 From 583617288e914b282f7c3278ff1403adef941f85 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 7 Aug 2022 23:32:46 +0200 Subject: Fix clang --- xmake/rules/c++/modules/modules_support/clang.lua | 32 ++--------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 4749f7fe3..35b7cdbc5 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -51,7 +51,6 @@ end -- function _add_headerunit_to_mapper(target, bmi) local cache = common.localcache():get("mapflags") or {} - local modulefileflag = get_modulefileflag(target) local mapflag = format("%s%s", modulefileflag, bmi) if table.contains(cache, mapflag) then return @@ -61,17 +60,6 @@ function _add_headerunit_to_mapper(target, bmi) common.localcache():save("mapflags") end - local modulefileflag = get_modulefileflag(target) - for line in io.lines(file) do - if line:startswith(modulefileflag .. bmi) then - return - end - end - local f = io.open(file, "a") - f:print("%s%s", modulefileflag, bmi) - f:close() -end - -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) @@ -266,9 +254,8 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) -- append module mapper flags - for line in io.lines(mapper_file) do - target:add("cxxflags", line, {force = true}) - end + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) -- build modules local common_args = {modulecachepathflag .. cachedir} @@ -340,21 +327,6 @@ function get_builtinmodulemapflag(target) return builtinmodulemapflag or nil end -function get_modulemapfileflag(target) - local modulemapfileflag = _g.modulemapfileflag - if modulemapfileflag == nil then - local compinst = target:compiler("cxx") - local mapper_file = path.join(os.tmpfile(), "mapper.txt") - os.touch(mapper_file) - if compinst:has_flags("-fmodule-map-file=" .. mapper_file, "cxxflags", {flagskey = "clang_module_map_file"}) then - modulemapfileflag = "-fmodule-map-file=" - end - assert(modulemapfileflag, "compiler(clang): does not support c++ module!") - _g.modulemapfileflag = modulemapfileflag or false - end - return modulemapfileflag or nil -end - function get_implicitmodulesflag(target) local implicitmodulesflag = _g.implicitmodulesflag if implicitmodulesflag == nil then -- cgit v1.3.1 From c6ee1e60c83626215ba3f1bf8471fcc72ab3d4b4 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 21:01:10 +0800 Subject: fix tests --- tests/projects/c++/modules/class/test.lua | 8 +++++--- tests/projects/c++/modules/cpp_with_moduledeps/test.lua | 8 +++++--- tests/projects/c++/modules/dependence/test.lua | 8 +++++--- tests/projects/c++/modules/dependence2/test.lua | 8 +++++--- tests/projects/c++/modules/hello with spaces/test.lua | 8 +++++--- tests/projects/c++/modules/hello/test.lua | 8 +++++--- tests/projects/c++/modules/impl_unit/test.lua | 8 +++++--- tests/projects/c++/modules/inline_and_template/test.lua | 8 +++++--- tests/projects/c++/modules/staticlib/test.lua | 8 +++++--- tests/projects/c++/modules/submodules/test.lua | 8 +++++--- tests/projects/c++/modules/submodules2/test.lua | 8 +++++--- 11 files changed, 55 insertions(+), 33 deletions(-) diff --git a/tests/projects/c++/modules/class/test.lua b/tests/projects/c++/modules/class/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/class/test.lua +++ b/tests/projects/c++/modules/class/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/test.lua b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/cpp_with_moduledeps/test.lua +++ b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/dependence/test.lua b/tests/projects/c++/modules/dependence/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/dependence/test.lua +++ b/tests/projects/c++/modules/dependence/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/dependence2/test.lua b/tests/projects/c++/modules/dependence2/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/dependence2/test.lua +++ b/tests/projects/c++/modules/dependence2/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/hello with spaces/test.lua b/tests/projects/c++/modules/hello with spaces/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/hello with spaces/test.lua +++ b/tests/projects/c++/modules/hello with spaces/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/hello/test.lua b/tests/projects/c++/modules/hello/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/hello/test.lua +++ b/tests/projects/c++/modules/hello/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/impl_unit/test.lua b/tests/projects/c++/modules/impl_unit/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/impl_unit/test.lua +++ b/tests/projects/c++/modules/impl_unit/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/inline_and_template/test.lua b/tests/projects/c++/modules/inline_and_template/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/inline_and_template/test.lua +++ b/tests/projects/c++/modules/inline_and_template/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/staticlib/test.lua b/tests/projects/c++/modules/staticlib/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/staticlib/test.lua +++ b/tests/projects/c++/modules/staticlib/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/submodules/test.lua b/tests/projects/c++/modules/submodules/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/submodules/test.lua +++ b/tests/projects/c++/modules/submodules/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then diff --git a/tests/projects/c++/modules/submodules2/test.lua b/tests/projects/c++/modules/submodules2/test.lua index 76b141d6b..b2cc5b3da 100644 --- a/tests/projects/c++/modules/submodules2/test.lua +++ b/tests/projects/c++/modules/submodules2/test.lua @@ -5,13 +5,15 @@ function main(t) local test = false if is_subhost("windows") then test = true - elseif is_host("linux", "macosx") then + elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + test = true + end + elseif is_host("macosx") then local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then test = true - elseif gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true end end if test then -- cgit v1.3.1 From eac8fac2b08d6d2d16b7b9fe091e5594d091027d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Aug 2022 23:20:35 +0800 Subject: improve build rules --- tests/apis/rules/xmake.lua | 7 +++++ xmake/actions/build/build.lua | 62 ++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 5a6e5d546..1ffc45b04 100644 --- a/tests/apis/rules/xmake.lua +++ b/tests/apis/rules/xmake.lua @@ -148,3 +148,10 @@ target("test") add_files("src/index.md") add_files("src/test.c.in", {rule = "c code"}) + before_build(function (target) + print("target: before_build") + end) + + after_build(function (target) + print("target: after_build") + end) diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index a32b8d705..3eddf1610 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -37,25 +37,27 @@ function _clean_target(target) end end --- add builtin batch jobs -function _add_batchjobs_builtin(batchjobs, rootjob, target) +-- add batch jobs for rules +function _add_batchjobs_for_rules(batchjobs, rootjob, target, suffix) -- uses the rules script? local job, job_leaf for _, r in irpairs(target:orderules()) do -- reverse rules order for batchjobs:addjob() - local script = r:script("build") + local scriptname = "build" .. (suffix and ("_" .. suffix) or "") + local script = r:script(scriptname) if script then - if r:extraconf("build", "batch") then - job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):on_build(): no returned job!", r:name()) + if r:extraconf(scriptname, "batch") then + job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):%s(): no returned job!", r:name(), scriptname) else - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total) + job = batchjobs:addjob("rule/" .. r:name() .. "/" .. scriptname, function (index, total) script(target, {progress = (index * 100) / total}) end, {rootjob = job or rootjob}) end else - local buildcmd = r:script("buildcmd") + scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local buildcmd = r:script(scriptname) if buildcmd then - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total) + job = batchjobs:addjob("rule/" .. r:name() .. "/" .. scriptname, function (index, total) local batchcmds_ = batchcmds.new({target = target}) buildcmd(target, batchcmds_, {progress = (index * 100) / total}) batchcmds_:runcmds({dryrun = option.get("dry-run")}) @@ -63,6 +65,14 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target) end end end + return job, job_leaf or job +end + +-- add builtin batch jobs +function _add_batchjobs_builtin(batchjobs, rootjob, target) + + -- add batchjobs for rules + local job, job_leaf = _add_batchjobs_for_rules(batchjobs, rootjob, target) -- uses the builtin target script if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object()) then @@ -125,19 +135,6 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) if after_build then after_build(target, {progress = progress}) end - for _, r in ipairs(target:orderules()) do - local after_build = r:script("build_after") - if after_build then - after_build(target, {progress = progress}) - else - local after_buildcmd = r:script("buildcmd_after") - if after_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - after_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({dryrun = option.get("dry-run")}) - end - end - end -- restore environments if oldenvs then @@ -146,8 +143,14 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) end, {rootjob = rootjob}) + -- add batchjobs for rules/build_after + local rules_job_build_after, rules_job_build_after_leaf = _add_batchjobs_for_rules(batchjobs, job_build_after, target, "after") + -- add batch jobs for target, @note only on_build script support batch jobs - local job_build, job_build_leaf = _add_batchjobs(batchjobs, job_build_after, target) + local job_build, job_build_leaf = _add_batchjobs(batchjobs, rules_job_build_after_leaf or job_build_after, target) + + -- add batchjobs for rules/build_before + local rules_job_build_before, rules_job_build_before_leaf = _add_batchjobs_for_rules(batchjobs, job_build_leaf, target, "before") -- add before_build job for target local job_build_before = batchjobs:addjob(target:name() .. "/before_build", function (index, total) @@ -166,20 +169,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) if before_build then before_build(target, {progress = progress}) end - for _, r in ipairs(target:orderules()) do - local before_build = r:script("build_before") - if before_build then - before_build(target, {progress = progress}) - else - local before_buildcmd = r:script("buildcmd_before") - if before_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - before_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({dryrun = option.get("dry-run")}) - end - end - end - end, {rootjob = job_build_leaf}) + end, {rootjob = rules_job_build_before_leaf or job_build_leaf}) return job_build_before, job_build, job_build_after end -- cgit v1.3.1 From 3652c9429dd47dbf08670f5ee8a89be00cf8693b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:54:49 +0200 Subject: Clean code --- xmake/rules/c++/modules/modules_support/gcc.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 65dc45782..8f3bacf72 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -162,7 +162,6 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, -- build headerunits local projectdir = os.projectdir() - local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then @@ -209,7 +208,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- build headerunits local projectdir = os.projectdir() - local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) local objectfile = target:objectfile(file) -- cgit v1.3.1 From e714ded62e800258e228942758fe7e809adca544 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:54:59 +0200 Subject: Add batchjobs for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 113 ++++++++++++++++++++-- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 35b7cdbc5..bff8cb7cb 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -143,13 +143,13 @@ function generate_dependencies(target, sourcebatch, opt) progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) end - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) - if not os.isdir(outdir) then - os.mkdir(outdir) + local outputdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end -- no support of p1689 atm - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + local jsonfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".json")) common.fallback_generate_dependencies(target, jsonfile, sourcefile) changed = true @@ -160,6 +160,38 @@ function generate_dependencies(target, sourcebatch, opt) return changed end +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + + -- get cachedirs + local stlcachedir = common.stlmodules_cachedir(target) + + -- get headerunits flags + local modulecachepathflag = get_modulecachepathflag(target) + local modulefileflag = get_modulefileflag(target) + + -- build headerunits + local projectdir = os.projectdir() + for i, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_headerunit_to_mapper(target, bmifile) + end + end + end +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -191,6 +223,61 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- generate target user header units for batchjobs +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + + -- get cachedirs + local cachedir = common.modules_cachedir(target) + + -- get headerunits flags + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleflag = get_emitmoduleflag(target) + local modulefileflag = get_modulefileflag(target) + + -- build headerunits + local objectfiles = {} + local flags = {} + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) + + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path)) + end + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} + if headerunit.type == ":quote" then + table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) + elseif headerunit.type == ":angle" then + table.join2(args, {"-x", "c++-system-header", headerunit.name}) + end + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_headerunit_to_mapper(target, bmifile) + end +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -213,16 +300,16 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) - local outdir + local outputdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - outdir = path.join(cachedir, path.directory(headerunit.path)) + outputdir = path.join(cachedir, path.directory(headerunit.path)) end - batchcmds:mkdir(outdir) + batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} @@ -292,6 +379,14 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + function get_bmi_extension() return ".pcm" end -- cgit v1.3.1 From 3a417fd416d178f8469af0e71610ec4b4f733971 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:55:10 +0200 Subject: Add batchjobs for msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 96 ++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b2b2e605a..7cf1c63b1 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -150,6 +150,41 @@ function generate_dependencies(target, sourcebatch, opt) return changed end +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + 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!") + + -- get cachedirs + local stlcachedir = common.stlmodules_cachedir(target) + + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + for _, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + local objectfile = bmifile .. ".obj" + if not os.isfile(bmifile) or not os.isfile(objectfile) then + batchjobs:addjob(headerunit.name, function(index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) + _add_objectfile_to_link_arguments(objectfile) + end + end +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -186,6 +221,59 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- generate target user header units for batchcmds +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + 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!") + + -- get cachedirs + local cachedir = common.modules_cachedir(target) + + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + -- if path is relative then its a subtarget path + outputdir = path.join(cachedir, path.is_absolute(headerunit.path) and path.directory(headerunit.path):sub(3) or headerunit.path) + end + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = path.join(outputdir, bmifilename) + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) + _add_objectfile_to_link_arguments(objectfile) + end +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -236,6 +324,14 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") -- cgit v1.3.1 From 1fb045a19472a8d04d24cb41c49a3bf75b2767d2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:40:44 +0800 Subject: add batchjobs for gcc --- tests/apis/rules/xmake.lua | 6 ++ xmake/rules/c++/modules/modules_support/common.lua | 32 ++++--- xmake/rules/c++/modules/modules_support/gcc.lua | 105 +++++++++++++++++---- xmake/rules/c++/modules/xmake.lua | 47 +++++---- 4 files changed, 133 insertions(+), 57 deletions(-) diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 1ffc45b04..7d67f0dca 100644 --- a/tests/apis/rules/xmake.lua +++ b/tests/apis/rules/xmake.lua @@ -58,6 +58,12 @@ rule("stub2") after_build(function (target) print("rule(stub2): after_build") end) + before_build_files(function (target) + print("rule(stub2): before_build_files") + end) + after_build_files(function (target) + print("rule(stub2): after_build_files") + end) -- define rule: stub1 rule("stub1") diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 34d014238..e9ef0fb62 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -411,20 +411,24 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) io.writefile(jsonfile, jsondata) end --- generate dependencies -function generate_dependencies(target, sourcebatch, opt) - local modules = localcache():get("modules") - local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) - if changed or modules == nil then - local moduleinfos = load_moduleinfos(target, sourcebatch) - modules = parse_dependency_data(target, moduleinfos) - localcache():set("modules", modules) - localcache():save() +-- get module dependencies +function get_module_dependencies(target, sourcebatch, opt) + local modules = _g.modules + if modules == nil then + modules = localcache():get("modules") + local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) + if changed or modules == nil then + local moduleinfos = load_moduleinfos(target, sourcebatch) + modules = parse_dependency_data(target, moduleinfos) + localcache():set("modules", modules) + localcache():save() + end + _g.modules = modules end return modules end --- generate headerunits for batchjobs, TODO +-- generate headerunits for batchjobs function generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) -- get headerunits info @@ -435,11 +439,11 @@ function generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modu local headerunits_flags if stl_headerunits then headerunits_flags = headerunits_flags or {} --- table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchjobs(target, batchjobs, stl_headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchjobs(target, batchjobs, stl_headerunits, opt)) end if headerunits then headerunits_flags = headerunits_flags or {} --- table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt)) end return headerunits_flags end @@ -463,7 +467,7 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu end end --- build modules for batchjobs, TODO +-- build modules for batchjobs function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) -- modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) @@ -484,4 +488,4 @@ function append_headerunits_objectfiles(target) elseif target:is_shared() == "shared" then target:add("shflags", cache, {force = true}) end -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 99045cf54..663e4ea07 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -131,15 +131,15 @@ function generate_dependencies(target, sourcebatch, opt) progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) end - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) - if not os.isdir(outdir) then - os.mkdir(outdir) + local outputdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + local jsonfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".json")) if trtbdflag and depfileflag and depoutputflag then - local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) - local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) + local ifile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".i")) + local dfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".d")) local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, depfileflag .. jsonfile, trtbdflag, depoutputfile .. target:objectfile(sourcefile), "-o", ifile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else @@ -154,12 +154,34 @@ function generate_dependencies(target, sourcebatch, opt) return changed end +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local stlcachedir = common.stlmodules_cachedir(target) + + -- build headerunits + local projectdir = os.projectdir() + local depmtime = 0 + for _, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {"-c", "-x", "c++-system-header", headerunit.name} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + end + end +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() - - -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) -- build headerunits @@ -172,21 +194,67 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) end +-- generate target user header units for batchjobs +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local cachedir = common.modules_cachedir(target) + + -- build headerunits + local projectdir = os.projectdir() + local depmtime = 0 + for _, headerunit in ipairs(headerunits) do + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local file = path.relative(headerunit.path, projectdir) + local objectfile = target:objectfile(file) + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path)) + end + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = { "-c" } + local headerunit_path + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) + headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + -- if path is relative then its a subtarget path + headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) + end + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + end +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- build headerunits @@ -195,17 +263,16 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) local objectfile = target:objectfile(file) - - local outdir + local outputdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - outdir = path.join(cachedir, path.directory(headerunit.path)) + outputdir = path.join(cachedir, path.directory(headerunit.path)) end - batchcmds:mkdir(outdir) + batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) local args = { "-c" } @@ -336,4 +403,4 @@ function get_depoutputflag(target) _g.depoutputflag = depoutputflag or false end return depoutputflag or nil -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 4117004cc..3efa123e6 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,35 +53,34 @@ rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - -- TODO parallel build support to accelerate `xmake build` to build modules - --[[ - before_build_files(function(target, batchjobs, sourcebatch, opt) - if not target:data("cxx.has_modules") then - sourcebatch.objectfiles = {} - return + before_build(function(target, batchjobs, opt) + local job + if target:data("cxx.has_modules") then + import("modules_support.common") + local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] + common.patch_sourcebatch(target, sourcebatch, opt) + + -- generate headerunits + local modules = common.get_module_dependencies(target, sourcebatch, opt) + batchjobs:group_enter(target:name() .. "/generate_headerunits") + common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + job = batchjobs:group_leave() end + return job or opt.rootjob + end, {batch = true}) - -- patch sourcebatch - import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) - - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) - - -- generate headerunits - local headerunits_flags = common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - if headerunits_flags then - target:add("cxxflags", headerunits_flags, {force = true, expand = false}) + -- parallel build support to accelerate `xmake build` to build modules + before_build_files(function(target, batchjobs, sourcebatch, opt) + if target:data("cxx.has_modules") then + import("modules_support.common") + local modules = common.get_module_dependencies(target, sourcebatch, opt) + common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) end - - -- build modules - common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - end, {batch = true})]] + end, {batch = true}) -- serial compilation only, usually used to support project generator before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) if not target:data("cxx.has_modules") then - sourcebatch.objectfiles = {} return end @@ -89,8 +88,8 @@ rule("c++.build.modules.builder") import("modules_support.common") common.patch_sourcebatch(target, sourcebatch, opt) - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) + -- get module dependencies + local modules = common.get_module_dependencies(target, sourcebatch, opt) -- generate headerunits common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cgit v1.3.1 From e96c32a19877939a4e325bb3afccef873b47ce35 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:45:38 +0800 Subject: fix batchjobs for gcc/headerunits --- xmake/rules/c++/modules/modules_support/common.lua | 3 ++- xmake/rules/c++/modules/modules_support/gcc.lua | 23 ++++++++++++++++------ xmake/rules/c++/modules/xmake.lua | 1 + 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index e9ef0fb62..52a428874 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -416,6 +416,7 @@ function get_module_dependencies(target, sourcebatch, opt) local modules = _g.modules if modules == nil then modules = localcache():get("modules") + opt.progress = opt.progress or 0 local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) if changed or modules == nil then local moduleinfos = load_moduleinfos(target, sourcebatch) @@ -470,7 +471,7 @@ end -- build modules for batchjobs function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) --- modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) end -- build modules for batchcmds diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 663e4ea07..af328b0b2 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -171,10 +171,10 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {"-c", "-x", "c++-system-header", headerunit.name} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = opt.rootjob}) end + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) end end @@ -213,6 +213,13 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, for _, headerunit in ipairs(headerunits) do local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + local headerunit_path + if headerunit.type == ":quote" then + headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) + elseif headerunit.type == ":angle" then + -- if path is relative then its a subtarget path + headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) + end batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -234,20 +241,16 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- generate headerunit local args = { "-c" } - local headerunit_path if headerunit.type == ":quote" then table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) - headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) elseif headerunit.type == ":angle" then table.join2(args, { "-x", "c++-system-header", headerunit.name }) - -- if path is relative then its a subtarget path - headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) end os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = opt.rootjob}) + _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) end end @@ -296,6 +299,14 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3efa123e6..c888a83fb 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,6 +52,7 @@ rule("c++.build.modules") rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + add_deps("c++.build.modules.dependencies") before_build(function(target, batchjobs, opt) local job -- cgit v1.3.1 From bc068bdb03fa9e75cd8dfe056a06790956934eba Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:13 +0800 Subject: fix path --- xmake/rules/c++/modules/modules_support/gcc.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index af328b0b2..65dc45782 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -211,9 +211,17 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local projectdir = os.projectdir() local depmtime = 0 for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, projectdir) + local objectfile = target:objectfile(file) + local outputdir + local headerunit_path + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path)) + end local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) - local headerunit_path if headerunit.type == ":quote" then headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) elseif headerunit.type == ":angle" then @@ -223,14 +231,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - local file = path.relative(headerunit.path, projectdir) - local objectfile = target:objectfile(file) - local outputdir - if headerunit.type == ":quote" then - outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - outputdir = path.join(cachedir, path.directory(headerunit.path)) - end local objectdir = path.directory(objectfile) if not os.isdir(objectdir) then os.mkdir(objectdir) -- cgit v1.3.1 From aaa5b2c37ec355cf2746f2d854517b3f43afcaf5 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:26 +0800 Subject: remvoe deps --- xmake/rules/c++/modules/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index c888a83fb..3efa123e6 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,7 +52,6 @@ rule("c++.build.modules") rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - add_deps("c++.build.modules.dependencies") before_build(function(target, batchjobs, opt) local job -- cgit v1.3.1 From 4abd6737364ffec07d9813c63d89e0ae90240315 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:33 +0800 Subject: add comments --- xmake/rules/c++/modules/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3efa123e6..1d117e78b 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,6 +53,7 @@ rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + -- parallel build support to accelerate `xmake build` to build headerunits before_build(function(target, batchjobs, opt) local job if target:data("cxx.has_modules") then -- cgit v1.3.1 From d0e4316018f9d75742b26b3abf75860d129c31c8 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:24:30 +0800 Subject: remove cxx sourcekind for modules --- xmake/rules/c++/modules/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 1d117e78b..7048ec49b 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -50,7 +50,6 @@ rule("c++.build.modules") -- build modules rule("c++.build.modules.builder") - set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- parallel build support to accelerate `xmake build` to build headerunits -- cgit v1.3.1 From ad67a37fe4981f68c52ae1e7497090a60a30edab Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:31:35 +0800 Subject: fix module dpes --- xmake/rules/c++/modules/modules_support/common.lua | 9 +++---- xmake/rules/c++/modules/xmake.lua | 28 ++++++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 52a428874..ee1016d68 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -413,18 +413,19 @@ end -- get module dependencies function get_module_dependencies(target, sourcebatch, opt) - local modules = _g.modules + local cachekey = target:name() .. "/" .. sourcebatch.rulename + local modules = memcache():get2("modules", cachekey) if modules == nil then - modules = localcache():get("modules") + modules = localcache():get2("modules", cachekey) opt.progress = opt.progress or 0 local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) if changed or modules == nil then local moduleinfos = load_moduleinfos(target, sourcebatch) modules = parse_dependency_data(target, moduleinfos) - localcache():set("modules", modules) + localcache():set2("modules", cachekey, modules) localcache():save() end - _g.modules = modules + memcache():set2("modules", cachekey, modules) end return modules end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 7048ec49b..3c69600bd 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -50,6 +50,7 @@ rule("c++.build.modules") -- build modules rule("c++.build.modules.builder") + set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- parallel build support to accelerate `xmake build` to build headerunits @@ -75,27 +76,28 @@ rule("c++.build.modules.builder") import("modules_support.common") local modules = common.get_module_dependencies(target, sourcebatch, opt) common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + else + sourcebatch.objectfiles = {} end end, {batch = true}) -- serial compilation only, usually used to support project generator before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) - if not target:data("cxx.has_modules") then - return - end - - -- patch sourcebatch - import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) + if target:data("cxx.has_modules") then + import("modules_support.common") - -- get module dependencies - local modules = common.get_module_dependencies(target, sourcebatch, opt) + -- patch sourcebatch + common.patch_sourcebatch(target, sourcebatch, opt) - -- generate headerunits - common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + -- generate headerunits + local modules = common.get_module_dependencies(target, sourcebatch, opt) + common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - -- build modules - common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + -- build modules + common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + else + sourcebatch.objectfiles = {} + end end) before_link(function(target) -- cgit v1.3.1 From 969c1371fde82493d75766681c800107b8359981 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:31:54 +0800 Subject: add comments --- xmake/rules/c++/modules/xmake.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3c69600bd..42c1709b4 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -77,6 +77,7 @@ rule("c++.build.modules.builder") local modules = common.get_module_dependencies(target, sourcebatch, opt) common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) else + -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} end end, {batch = true}) @@ -96,6 +97,7 @@ rule("c++.build.modules.builder") -- build modules common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) else + -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} end end) -- cgit v1.3.1 From bd1263aa60a502120e06eb3fd077d69c689dc5d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:27:34 +0800 Subject: build batchjobs modules for gcc --- xmake/rules/c++/modules/modules_support/common.lua | 41 ++++++++++++++++ xmake/rules/c++/modules/modules_support/gcc.lua | 55 +++++++++++++++++++--- xmake/rules/c++/modules/xmake.lua | 5 +- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index ee1016d68..31ab47a81 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -469,6 +469,46 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu end end +-- build batch jobs for module dependencies +function _build_batchjobs_for_moduledeps(modules, batchjobs, rootjob, jobrefs, moduleinfo) + local targetjob_ref = jobrefs[moduleinfo.name] + if targetjob_ref then + batchjobs:add(targetjob_ref, rootjob) + else + local modulejob = batchjobs:add(moduleinfo.job, rootjob) + if modulejob then + jobrefs[moduleinfo.name] = modulejob + for _, depname in ipairs(moduleinfo.deps) do + local dep = modules[depname] + if dep then -- maybe nil, e.g. `import ;` + _build_batchjobs_for_moduledeps(modules, batchjobs, modulejob, jobrefs, dep) + end + end + end + end +end + +-- build batchjobs for modules +function build_batchjobs_for_modules(modules, batchjobs, rootjob) + local depset = hashset.new() + for _, moduleinfo in pairs(modules) do + assert(moduleinfo.job) + for _, depname in ipairs(moduleinfo.deps) do + depset:insert(depname) + end + end + local modules_root = {} + for _, moduleinfo in pairs(modules) do + if not depset:has(moduleinfo.name) then + table.insert(modules_root, moduleinfo) + end + end + local jobrefs = {} + for _, moduleinfo in pairs(modules_root) do + _build_batchjobs_for_moduledeps(modules, batchjobs, rootjob, jobrefs, moduleinfo) + end +end + -- build modules for batchjobs function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) @@ -481,6 +521,7 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op modules_support(target).build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) end +-- append headerunits objectfiles to link function append_headerunits_objectfiles(target) local cache = localcache():get("headerunit_objectfiles") or {} if target:is_binary() then diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 8f3bacf72..e62721cf3 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -299,10 +299,55 @@ end -- build module files for batchjobs function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local common_args = {"-x", "c++"} + local cachedir = common.modules_cachedir(target) + + -- build modules + local projectdir = os.projectdir() + local depmtime = 0 + local provided_modules = {} + 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!") + end + end + + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + local args = {"-o", objectfile, "-c", provide.sourcefile} + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + 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) end -- build module files for batchcmds @@ -310,8 +355,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() local common_args = {"-x", "c++"} - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- build modules diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 42c1709b4..d6098b95e 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,6 +53,7 @@ rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + -- generate headerunits -- parallel build support to accelerate `xmake build` to build headerunits before_build(function(target, batchjobs, opt) local job @@ -60,8 +61,6 @@ rule("c++.build.modules.builder") import("modules_support.common") local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] common.patch_sourcebatch(target, sourcebatch, opt) - - -- generate headerunits local modules = common.get_module_dependencies(target, sourcebatch, opt) batchjobs:group_enter(target:name() .. "/generate_headerunits") common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) @@ -70,10 +69,12 @@ rule("c++.build.modules.builder") return job or opt.rootjob end, {batch = true}) + -- build modules -- parallel build support to accelerate `xmake build` to build modules before_build_files(function(target, batchjobs, sourcebatch, opt) if target:data("cxx.has_modules") then import("modules_support.common") + common.patch_sourcebatch(target, sourcebatch, opt) local modules = common.get_module_dependencies(target, sourcebatch, opt) common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) else -- cgit v1.3.1 From a7754666add7c76fe8a255e6c84800fa0cb44320 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:31:34 +0800 Subject: build batchjobs for clang/msvc --- xmake/rules/c++/modules/modules_support/clang.lua | 77 +++++++++++++++------ xmake/rules/c++/modules/modules_support/gcc.lua | 3 +- xmake/rules/c++/modules/modules_support/msvc.lua | 83 +++++++++++++++++------ 3 files changed, 121 insertions(+), 42 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index bff8cb7cb..f11350764 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -198,8 +198,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) @@ -230,8 +228,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleflag = get_emitmoduleflag(target) local modulefileflag = get_modulefileflag(target) @@ -285,8 +281,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleflag = get_emitmoduleflag(target) local modulefileflag = get_modulefileflag(target) @@ -329,14 +323,67 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local cachedir = common.modules_cachedir(target) + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) + + -- append module mapper flags + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) + + -- build modules + local common_args = {modulecachepathflag .. cachedir} + local provided_modules = {} + 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!") + end + end + + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + local args = {emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + end + moduleinfo.name = name + provided_modules[name] = moduleinfo + _add_module_to_mapper(target, name, bmifile) + target:add("objectfiles", objectfile) + end + end + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") - - -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) @@ -379,14 +426,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:set_depmtime(depmtime) end --- build module files for batchjobs -function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) -end - function get_bmi_extension() return ".pcm" end @@ -524,4 +563,4 @@ function has_headerunitsupport(target) _g.support_headerunits = support_headerunits or false end return support_headerunits or nil -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e62721cf3..a37346bad 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -306,7 +306,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- build modules local projectdir = os.projectdir() - local depmtime = 0 local provided_modules = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -327,12 +326,12 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local moduleinfo = table.copy(provide) moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) depend.on_changed(function() - local args = {"-o", objectfile, "-c", provide.sourcefile} progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) local objectdir = path.directory(objectfile) if not os.isdir(objectdir) then os.mkdir(objectdir) end + local args = {"-o", objectfile, "-c", provide.sourcefile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) end) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7cf1c63b1..64ca0dae3 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -155,6 +155,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local stlcachedir = common.stlmodules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -163,9 +164,6 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local stlcachedir = common.stlmodules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} for _, headerunit in ipairs(headerunits) do @@ -190,6 +188,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local stlcachedir = common.stlmodules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -198,9 +197,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local stlcachedir = common.stlmodules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local depmtime = 0 @@ -226,6 +222,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -234,9 +231,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local cachedir = common.modules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -279,6 +273,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -287,9 +282,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local cachedir = common.modules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -326,10 +318,63 @@ end -- build module files for batchjobs function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) + + -- get flags + local ifcoutputflag = get_ifcoutputflag(target) + local interfaceflag = get_interfaceflag(target) + local referenceflag = get_referenceflag(target) + + -- append module mapper flags + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) + + -- build modules + local common_args = {"-TP"} + local provided_modules = {} + 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!") + end + end + + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + end + moduleinfo.name = name + provided_modules[name] = moduleinfo + _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) + target:add("objectfiles", objectfile) + end + end + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) end -- build module files for batchcmds @@ -337,8 +382,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- get flags @@ -375,9 +418,7 @@ 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_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -526,4 +567,4 @@ function get_scandependenciesflag(target) _g.scandependenciesflag = scandependenciesflag or false end return scandependenciesflag or nil -end \ No newline at end of file +end -- cgit v1.3.1 From 8d2cfef3b5814c32d08e89d7d17d4242b203331b Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:35:20 +0800 Subject: fix check for clang/headerunits --- xmake/rules/c++/modules/modules_support/clang.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index f11350764..226756d6c 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -163,13 +163,10 @@ end -- generate target stl header units for batchjobs function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) local compinst = target:compiler("cxx") - - -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- build headerunits local projectdir = os.projectdir() @@ -200,6 +197,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local stlcachedir = common.stlmodules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- build headerunits local projectdir = os.projectdir() -- cgit v1.3.1 From 71ee1cb7b921c2b98dda8eecebc641ddac71681d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:32:22 +0800 Subject: fix mapper for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 76 ++++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 226756d6c..1b086c27a 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -33,15 +33,14 @@ import("common") -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- function _add_module_to_mapper(target, module, bmi) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.localcache():get("mapflags") or {} local modulefileflag = get_modulefileflag(target) local mapflag = format("%s%s=%s", modulefileflag, module, bmi) - if table.contains(cache, mapflag) then + if table.contains(mapflags, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) - common.localcache():save("mapflags") + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) end -- add a header unit into the mapper @@ -50,16 +49,25 @@ end -- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- function _add_headerunit_to_mapper(target, bmi) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.memcache():get("mapflags") or {} local mapflag = format("%s%s", modulefileflag, bmi) if table.contains(cache, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) +end + +-- flush mapflags to mapper file cache +function _flush_mapflags_to_mapper() common.localcache():save("mapflags") end +-- get mapflags from mapper +function _get_mapflags_from_mapper() + return common.localcache():get("mapflags") +end + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) @@ -187,6 +195,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end end end + _flush_mapflags_to_mapper() end -- generate target stl header units for batchcmds @@ -217,6 +226,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end -- generate target user header units for batchjobs @@ -270,6 +280,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {rootjob = opt.rootjob}) _add_headerunit_to_mapper(target, bmifile) end + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -319,6 +330,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end -- build module files for batchjobs @@ -328,10 +340,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - -- build modules local common_args = {modulecachepathflag .. cachedir} local provided_modules = {} @@ -373,6 +381,13 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) end end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end -- build batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) @@ -385,13 +400,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - - -- build modules - local common_args = {modulecachepathflag .. cachedir} - local depmtime = 0 + -- we need update mapper first for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -407,6 +416,31 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end end + local bmifile = provide.bmi + _add_module_to_mapper(target, name, bmifile) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + + -- build modules + local depmtime = 0 + local common_args = {modulecachepathflag .. cachedir} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + local name, provide + for k, v in pairs(m.provides) do + name = k + provide = v + break + end local bmifile = provide.bmi local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -414,10 +448,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - - _add_module_to_mapper(target, name, bmifile) - - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end -- cgit v1.3.1 From 02b60934d7425d5dc9f77cf3a07d956cf4922b98 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:34:01 +0800 Subject: improve mapper for msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 70 +++++++++++++++++------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 64ca0dae3..7ac93273f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -34,16 +34,25 @@ import("common") -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- function _add_module_to_mapper(argument, module) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.localcache():get("mapflags") or {} local mapflag = format("%s %s", argument, module) - if table.contains(cache, mapflag) then + if table.contains(mapflags, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) +end + +-- flush mapflags to mapper file cache +function _flush_mapflags_to_mapper() common.localcache():save("mapflags") end +-- get mapflags from mapper +function _get_mapflags_from_mapper() + return common.localcache():get("mapflags") +end + -- add an objectfile to the linker args -- -- e.g @@ -181,6 +190,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, _add_objectfile_to_link_arguments(objectfile) end end + _flush_mapflags_to_mapper() end -- generate target stl header units for batchcmds @@ -215,6 +225,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -266,6 +277,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) _add_objectfile_to_link_arguments(objectfile) end + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -314,6 +326,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end -- build module files for batchjobs @@ -328,10 +341,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - -- build modules local common_args = {"-TP"} local provided_modules = {} @@ -372,6 +381,13 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) end end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end -- build batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) @@ -389,13 +405,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - - -- build modules - local common_args = {"-TP"} - local depmtime = 0 + -- we need update mapper first for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -412,18 +422,40 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + + -- build modules + local common_args = {"-TP"} + local depmtime = 0 + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + local name, provide + for k, v in pairs(m.provides) do + name = k + provide = v + break + end + local bmifile = provide.bmi + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end - batchcmds:set_depmtime(depmtime) end -- cgit v1.3.1 From 1c039fcf27683545adb20ca316d42b1123282719 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:35:50 +0800 Subject: clean module caches --- xmake/rules/c++/modules/xmake.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index d6098b95e..23f9a0f77 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -103,11 +103,22 @@ rule("c++.build.modules.builder") end end) - before_link(function(target) + before_link(function (target) import("modules_support.common") common.append_headerunits_objectfiles(target) end) + after_clean(function (target) + import("core.base.option") + import("modules_support.common") + os.tryrm(common.modules_cachedir(target)) + if option.get("all") then + os.tryrm(common.stlmodules_cachedir(target)) + common.localcache():clear() + common.localcache():save() + end + end) + -- install modules rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- cgit v1.3.1 From af7118dcc94785f628abe1cea5cd030514ea9e88 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:42:52 +0800 Subject: improve mapper for clang/msvc --- xmake/rules/c++/modules/modules_support/clang.lua | 15 +++++++++------ xmake/rules/c++/modules/modules_support/msvc.lua | 14 +++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 1b086c27a..866669257 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -367,6 +367,15 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op if not os.isdir(objectdir) then os.mkdir(objectdir) end + -- append module mapper flags first + -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper + if not target:data("cxx.add_modules_mapflags") then + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + target:data_set("cxx.add_modules_mapflags", true) + end local args = {emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) @@ -383,12 +392,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op end _flush_mapflags_to_mapper() - -- append module mapper flags - local mapflags = _get_mapflags_from_mapper() - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - -- build batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7ac93273f..bcc781248 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -368,6 +368,15 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op if not os.isdir(objectdir) then os.mkdir(objectdir) end + -- append module mapper flags first + -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper + if not target:data("cxx.add_modules_mapflags") then + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + target:data_set("cxx.add_modules_mapflags", true) + end local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) @@ -383,11 +392,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op end _flush_mapflags_to_mapper() - -- append module mapper flags - local mapflags = _get_mapflags_from_mapper() - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end -- build batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) -- cgit v1.3.1 From ebaa26b0153d68a0f8cee6e135793fd079cca5f4 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:58:25 +0800 Subject: improve test --- tests/projects/c++/modules/class/test.lua | 23 +----------- .../c++/modules/cpp_with_moduledeps/test.lua | 23 +----------- .../projects/c++/modules/dependence/CMakeLists.txt | 43 ++++++++++++++++++++++ tests/projects/c++/modules/dependence/test.lua | 23 +----------- tests/projects/c++/modules/dependence2/test.lua | 23 +----------- .../c++/modules/hello with spaces/test.lua | 23 +----------- tests/projects/c++/modules/hello/test.lua | 23 +----------- tests/projects/c++/modules/impl_unit/test.lua | 23 +----------- .../c++/modules/inline_and_template/test.lua | 23 +----------- tests/projects/c++/modules/staticlib/test.lua | 23 +----------- tests/projects/c++/modules/submodules/test.lua | 23 +----------- tests/projects/c++/modules/submodules2/test.lua | 23 +----------- tests/projects/c++/modules/test_base.lua | 21 +++++++++++ 13 files changed, 75 insertions(+), 242 deletions(-) create mode 100644 tests/projects/c++/modules/dependence/CMakeLists.txt create mode 100644 tests/projects/c++/modules/test_base.lua diff --git a/tests/projects/c++/modules/class/test.lua b/tests/projects/c++/modules/class/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/class/test.lua +++ b/tests/projects/c++/modules/class/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/cpp_with_moduledeps/test.lua b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/cpp_with_moduledeps/test.lua +++ b/tests/projects/c++/modules/cpp_with_moduledeps/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/dependence/CMakeLists.txt b/tests/projects/c++/modules/dependence/CMakeLists.txt new file mode 100644 index 000000000..19eb7793a --- /dev/null +++ b/tests/projects/c++/modules/dependence/CMakeLists.txt @@ -0,0 +1,43 @@ +# this is the build file for project +# it is autogenerated by the xmake build system. +# do not edit by hand. + +# project +cmake_minimum_required(VERSION 3.15.0) +cmake_policy(SET CMP0091 NEW) +project(dependence LANGUAGES CXX C) + +# target +add_executable(dependence "") +set_target_properties(dependence PROPERTIES OUTPUT_NAME "dependence") +set_target_properties(dependence PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/macosx/x86_64/release") +target_compile_options(dependence PRIVATE + $<$:-m64> + $<$:-m64> + $<$:-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk> + $<$:-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk> + $<$:-fmodules> + $<$:-fbuiltin-module-map> + $<$:-fimplicit-modules> + $<$:-fno-implicit-module-maps> +) +target_compile_features(dependence PRIVATE cxx_std_20) +if(MSVC) + set_property(TARGET dependence PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() +target_link_options(dependence PRIVATE + -m64 + -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk +) +target_sources(dependence PRIVATE + src/hello_impl.cpp + src/mod_impl.cpp + src/main.cpp + src/hello_impl.cpp + src/mod_impl.cpp + src/main.cpp + src/mod.mpp + src/hello.mpp +) + diff --git a/tests/projects/c++/modules/dependence/test.lua b/tests/projects/c++/modules/dependence/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/dependence/test.lua +++ b/tests/projects/c++/modules/dependence/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/dependence2/test.lua b/tests/projects/c++/modules/dependence2/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/dependence2/test.lua +++ b/tests/projects/c++/modules/dependence2/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/hello with spaces/test.lua b/tests/projects/c++/modules/hello with spaces/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/hello with spaces/test.lua +++ b/tests/projects/c++/modules/hello with spaces/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/hello/test.lua b/tests/projects/c++/modules/hello/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/hello/test.lua +++ b/tests/projects/c++/modules/hello/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/impl_unit/test.lua b/tests/projects/c++/modules/impl_unit/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/impl_unit/test.lua +++ b/tests/projects/c++/modules/impl_unit/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/inline_and_template/test.lua b/tests/projects/c++/modules/inline_and_template/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/inline_and_template/test.lua +++ b/tests/projects/c++/modules/inline_and_template/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/staticlib/test.lua b/tests/projects/c++/modules/staticlib/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/staticlib/test.lua +++ b/tests/projects/c++/modules/staticlib/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/submodules/test.lua b/tests/projects/c++/modules/submodules/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/submodules/test.lua +++ b/tests/projects/c++/modules/submodules/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/submodules2/test.lua b/tests/projects/c++/modules/submodules2/test.lua index b2cc5b3da..7717f8049 100644 --- a/tests/projects/c++/modules/submodules2/test.lua +++ b/tests/projects/c++/modules/submodules2/test.lua @@ -1,22 +1 @@ -import("lib.detect.find_tool") -import("core.base.semver") - -function main(t) - local test = false - if is_subhost("windows") then - test = true - elseif is_host("linux") then - local gcc = find_tool("gcc", {version = true}) - if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then - test = true - end - elseif is_host("macosx") then - local clang = find_tool("clang", {version = true}) - if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then - test = true - end - end - if test then - os.exec("xmake") - end -end +inherit(".test_base") diff --git a/tests/projects/c++/modules/test_base.lua b/tests/projects/c++/modules/test_base.lua new file mode 100644 index 000000000..68efbeaa0 --- /dev/null +++ b/tests/projects/c++/modules/test_base.lua @@ -0,0 +1,21 @@ +import("lib.detect.find_tool") +import("core.base.semver") + +function main(t) + if is_subhost("windows") then + os.exec("xmake f -c") + os.exec("xmake -r") + elseif is_host("linux") then + local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + os.exec("xmake f -c") + os.exec("xmake -r") + end + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then + os.exec("xmake clean -a") + os.exec("xmake f --toolchain=clang -c") + os.exec("xmake -r") + end + end +end -- cgit v1.3.1 From 6198c9de133d186a13bc9223c284416bb4a4f7bb Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Aug 2022 00:00:09 +0800 Subject: add missing flags --- xmake/rules/c++/modules/modules_support/clang.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 866669257..a115c1000 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -50,6 +50,7 @@ end -- function _add_headerunit_to_mapper(target, bmi) local mapflags = common.memcache():get("mapflags") or {} + local modulefileflag = get_modulefileflag(target) local mapflag = format("%s%s", modulefileflag, bmi) if table.contains(cache, mapflag) then return @@ -363,6 +364,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) depend.on_changed(function() progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local bmidir = path.directory(bmifile) + if not os.isdir(bmidir) then + os.mkdir(bmidir) + end local objectdir = path.directory(objectfile) if not os.isdir(objectdir) then os.mkdir(objectdir) @@ -447,6 +452,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local bmifile = provide.bmi local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) + batchcmds:mkdir(path.directory(bmifile)) batchcmds:mkdir(path.directory(objectfile)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) -- cgit v1.3.1 From f550fa3c35f412fd0cba433610d9e747f7d4be3f Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Aug 2022 00:54:48 +0800 Subject: add target:fileconfig_add --- xmake/core/project/target.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index b00cbe15a..faf11b3cc 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1280,6 +1280,24 @@ function _instance:fileconfig_set(sourcefile, info) self._FILESCONFIG = filesconfig end +-- add the config info to the given source file +function _instance:fileconfig_add(sourcefile, info) + local filesconfig = self._FILESCONFIG or {} + local fileconfig = filesconfig[sourcefile] + if fileconfig then + for k, v in pairs(info) do + if fileconfig[k] then + fileconfig[k] = table.join(fileconfig[k], v) + else + fileconfig[k] = v + end + end + else + filesconfig[sourcefile] = info + end + self._FILESCONFIG = filesconfig +end + -- get the source files function _instance:sourcefiles() -- cgit v1.3.1 From 172d2c7fcd0bf09fb24d286df3d2da5b556c291b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 06:56:47 +0200 Subject: Avoid building a same header unit at the same time --- xmake/rules/c++/modules/modules_support/msvc.lua | 37 +++++++++++++++--------- xmake/rules/c++/modules/xmake.lua | 6 ++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index bcc781248..d1a09cbeb 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -181,9 +181,14 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, if not os.isfile(bmifile) or not os.isfile(objectfile) then batchjobs:addjob(headerunit.name, function(index, total) depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + if not common.localcache():get2(headerunit.name, "building") then + common.localcache():set2(headerunit.name, "building", true) + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + common.localcache():set2(headerunit.name, "building", false) + end + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = opt.rootjob}) _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) @@ -259,18 +264,22 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local bmifile = path.join(outputdir, bmifilename) batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - local objectdir = path.directory(objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) - end - if not os.isdir(outputdir) then - os.mkdir(outputdir) - end + if not common.localcache():get2(headerunit.name, "building") then + common.localcache():set2(headerunit.name, "building", true) + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end - -- generate headerunit - local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + -- generate headerunit + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + common.localcache():set2(headerunit.name, "building", false) + end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = opt.rootjob}) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 23f9a0f77..05d7a76e9 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -61,10 +61,16 @@ rule("c++.build.modules.builder") import("modules_support.common") local sourcebatch = target:sourcebatches()["c++.build.modules.builder"] common.patch_sourcebatch(target, sourcebatch, opt) + + -- generate headerunits local modules = common.get_module_dependencies(target, sourcebatch, opt) batchjobs:group_enter(target:name() .. "/generate_headerunits") common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) job = batchjobs:group_leave() + + -- append module mapper flags + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) end return job or opt.rootjob end, {batch = true}) -- cgit v1.3.1 From 6d0a8f98c83d45a89182568f83ef8abec24752b3 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 09:50:26 +0200 Subject: Fix clang module compilation --- xmake/rules/c++/modules/modules_support/clang.lua | 139 +++++++++------------- xmake/rules/c++/modules/xmake.lua | 4 - 2 files changed, 57 insertions(+), 86 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index a115c1000..0deb6edeb 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -32,15 +32,19 @@ import("common") -- e.g -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- -function _add_module_to_mapper(target, module, bmi) - local mapflags = common.localcache():get("mapflags") or {} +function _add_module_to_mapper(target, bmi) + local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s=%s", modulefileflag, module, bmi) + local mapflag = format("%s%s", modulefileflag, bmi) if table.contains(mapflags, mapflag) then return end table.insert(mapflags, mapflag) - common.localcache():set("mapflags", mapflags) + common.localcache():set2(_mapper_cachekey(target), mapflags) +end + +function _mapper_cachekey(target) + return target:name() .. "_mapflags" end -- add a header unit into the mapper @@ -49,24 +53,25 @@ end -- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- function _add_headerunit_to_mapper(target, bmi) - local mapflags = common.memcache():get("mapflags") or {} + local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) local mapflag = format("%s%s", modulefileflag, bmi) - if table.contains(cache, mapflag) then + if table.contains(mapflags, mapflag) then return end table.insert(mapflags, mapflag) - common.localcache():set("mapflags", mapflags) + common.localcache():set(_mapper_cachekey(target), mapflags) end -- flush mapflags to mapper file cache -function _flush_mapflags_to_mapper() - common.localcache():save("mapflags") +function _flush_mapflags_to_mapper(target) + -- not using set2/get2 to flush only current target mapper + common.localcache():save(_mapper_cachekey(target)) end -- get mapflags from mapper -function _get_mapflags_from_mapper() - return common.localcache():get("mapflags") +function _get_mapflags_from_mapper(target) + return common.localcache():get(_mapper_cachekey(target)) or {} end -- load module support for the current target @@ -187,16 +192,16 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_headerunit_to_mapper(target, bmifile) + end end, {rootjob = opt.rootjob}) - - -- libc++ have a builtin module mapper - if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, bmifile) - end end end - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- generate target stl header units for batchcmds @@ -227,7 +232,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- generate target user header units for batchjobs @@ -238,7 +243,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local emitmoduleflag = get_emitmoduleflag(target) local modulefileflag = get_modulefileflag(target) -- build headerunits @@ -269,7 +273,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end -- generate headerunit - local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} + local args = { modulecachepathflag .. cachedir, "-c", "-o", bmifile} if headerunit.type == ":quote" then table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) elseif headerunit.type == ":angle" then @@ -278,10 +282,10 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + _add_headerunit_to_mapper(target, bmifile) end, {rootjob = opt.rootjob}) - _add_headerunit_to_mapper(target, bmifile) end - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- generate target user header units for batchcmds @@ -292,7 +296,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local emitmoduleflag = get_emitmoduleflag(target) local modulefileflag = get_modulefileflag(target) -- build headerunits @@ -316,7 +319,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) - local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} + local args = { modulecachepathflag .. cachedir, "-c", "-o", bmifile} if headerunit.type == ":quote" then table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) elseif headerunit.type == ":angle" then @@ -331,7 +334,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- build module files for batchjobs @@ -339,7 +342,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) + local modulefileflag = get_modulefileflag(target) -- build modules local common_args = {modulecachepathflag .. cachedir} @@ -375,27 +378,37 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- append module mapper flags first -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper if not target:data("cxx.add_modules_mapflags") then - local mapflags = _get_mapflags_from_mapper() + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper(target) if mapflags then target:add("cxxflags", mapflags, {force = true}) end + + -- append deps module mapper flags + for _, dep in ipairs(target:deps()) do + local mapflags = _get_mapflags_from_mapper(dep) + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + end target:data_set("cxx.add_modules_mapflags", true) end - local args = {emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} + local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + _add_module_to_mapper(target, bmifile) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) end) if m.requires then moduleinfo.deps = table.keys(m.requires) end moduleinfo.name = name provided_modules[name] = moduleinfo - _add_module_to_mapper(target, name, bmifile) target:add("objectfiles", objectfile) end end - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) -- build batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) @@ -406,37 +419,22 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local compinst = target:compiler("cxx") local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - - -- we need update mapper first - 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!") - end - end - - local bmifile = provide.bmi - _add_module_to_mapper(target, name, bmifile) - target:add("objectfiles", objectfile) - end - end - _flush_mapflags_to_mapper() + local modulefileflag = get_modulefileflag(target) -- append module mapper flags - local mapflags = _get_mapflags_from_mapper() + local mapflags = _get_mapflags_from_mapper(target) if mapflags then target:add("cxxflags", mapflags, {force = true}) end + -- append deps module mapper flags + for _, dep in ipairs(target:deps()) do + local mapflags = _get_mapflags_from_mapper(dep) + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + end + -- build modules local depmtime = 0 local common_args = {modulecachepathflag .. cachedir} @@ -450,17 +448,20 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op break end local bmifile = provide.bmi - local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } + local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) batchcmds:mkdir(path.directory(bmifile)) batchcmds:mkdir(path.directory(objectfile)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) + _add_module_to_mapper(target, bmifile) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) depmtime = math.max(depmtime, os.mtime(bmifile)) end end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper(target) end function get_bmi_extension() @@ -550,19 +551,6 @@ function get_modulecachepathflag(target) return modulecachepathflag or nil end -function get_emitmoduleflag(target) - local emitmoduleflag = _g.emitmoduleflag - if emitmoduleflag == nil then - local compinst = target:compiler("cxx") - if compinst:has_flags("-emit-module", "cxxflags", {flagskey = "clang_emit_module"}) then - emitmoduleflag = "-emit-module" - end - assert(emitmoduleflag, "compiler(clang): does not support c++ module!") - _g.emitmoduleflag = emitmoduleflag or false - end - return emitmoduleflag or nil -end - function get_modulefileflag(target) local modulefileflag = _g.modulefileflag if modulefileflag == nil then @@ -576,19 +564,6 @@ function get_modulefileflag(target) return modulefileflag or nil end -function get_emitmoduleinterfaceflag(target) - local emitmoduleinterfaceflag = _g.emitmoduleinterfaceflag - if emitmoduleinterfaceflag == nil then - local compinst = target:compiler("cxx") - if compinst:has_flags("-emit-module-interface", "cxxflags", {flagskey = "clang_emit_module_interface"}) then - emitmoduleinterfaceflag = "-emit-module-interface" - end - assert(emitmoduleinterfaceflag, "compiler(clang): does not support c++ module!") - _g.emitmoduleinterfaceflag = emitmoduleinterfaceflag or false - end - return emitmoduleinterfaceflag or nil -end - function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 05d7a76e9..276566a27 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -67,10 +67,6 @@ rule("c++.build.modules.builder") batchjobs:group_enter(target:name() .. "/generate_headerunits") common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) job = batchjobs:group_leave() - - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) end return job or opt.rootjob end, {batch = true}) -- cgit v1.3.1 From b3ed3546872d175fea0f6fa9ac0899b1e218ec00 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 12:04:18 +0200 Subject: Improve MSVC and clang module build --- xmake/rules/c++/modules/modules_support/clang.lua | 26 +++- xmake/rules/c++/modules/modules_support/common.lua | 3 +- xmake/rules/c++/modules/modules_support/msvc.lua | 146 +++++++++++---------- 3 files changed, 100 insertions(+), 75 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 0deb6edeb..2d6840f28 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -182,6 +182,11 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local modulefileflag = get_modulefileflag(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build headerunits local projectdir = os.projectdir() for i, headerunit in ipairs(headerunits) do @@ -198,7 +203,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, if not target:data_set("cxx.modules.use_libc++") then _add_headerunit_to_mapper(target, bmifile) end - end, {rootjob = opt.rootjob}) + end, {rootjob = flushjob}) end end _flush_mapflags_to_mapper(target) @@ -245,6 +250,11 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build headerunits local objectfiles = {} local flags = {} @@ -283,7 +293,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) _add_headerunit_to_mapper(target, bmifile) - end, {rootjob = opt.rootjob}) + end, {rootjob = flushjob}) end _flush_mapflags_to_mapper(target) end @@ -344,6 +354,11 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_stl_flush_mapper", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build modules local common_args = {modulecachepathflag .. cachedir} local provided_modules = {} @@ -385,7 +400,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op end -- append deps module mapper flags - for _, dep in ipairs(target:deps()) do + for _, dep in ipairs(target:orderdeps()) do local mapflags = _get_mapflags_from_mapper(dep) if mapflags then target:add("cxxflags", mapflags, {force = true}) @@ -408,10 +423,9 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) end end - _flush_mapflags_to_mapper(target) -- build batchjobs for modules - common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) + common.build_batchjobs_for_modules(provided_modules, batchjobs, flushjob) end -- build module files for batchcmds @@ -428,7 +442,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end -- append deps module mapper flags - for _, dep in ipairs(target:deps()) do + for _, dep in ipairs(target:orderdeps()) do local mapflags = _get_mapflags_from_mapper(dep) if mapflags then target:add("cxxflags", mapflags, {force = true}) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 31ab47a81..96468456f 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -523,7 +523,8 @@ end -- append headerunits objectfiles to link function append_headerunits_objectfiles(target) - local cache = localcache():get("headerunit_objectfiles") or {} + local cachekey = target:name() .. "headerunit_objectfiles" + local cache = localcache():get(cachekey) or {} if target:is_binary() then target:add("ldflags", cache, {force = true}) elseif target:is_static() == "static" then diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index d1a09cbeb..46a20993e 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -30,27 +30,32 @@ import("common") -- add a module or header unit into the mapper -- -- e.g --- /headerUnit:angle cstdint=cstdint.ifc +-- /headerUnit:angle Foo=build/.gens/Foo/rules/modules/cache/Foo.ifc -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- -function _add_module_to_mapper(argument, module) - local mapflags = common.localcache():get("mapflags") or {} +function _add_module_to_mapper(target, argument, module) + local mapflags = _get_mapflags_from_mapper(target) local mapflag = format("%s %s", argument, module) if table.contains(mapflags, mapflag) then return end table.insert(mapflags, mapflag) - common.localcache():set("mapflags", mapflags) + common.localcache():set(_mapper_cachekey(target), mapflags) +end + +function _mapper_cachekey(target) + return target:name() .. "_mapflags" end -- flush mapflags to mapper file cache -function _flush_mapflags_to_mapper() - common.localcache():save("mapflags") +function _flush_mapflags_to_mapper(target) + -- not using set2/get2 to flush only current target mapper + common.localcache():save(_mapper_cachekey(target)) end -- get mapflags from mapper -function _get_mapflags_from_mapper() - return common.localcache():get("mapflags") +function _get_mapflags_from_mapper(target) + return common.localcache():get(_mapper_cachekey(target)) or {} end -- add an objectfile to the linker args @@ -58,14 +63,15 @@ end -- e.g -- foo.obj -- -function _add_objectfile_to_link_arguments(objectfile) - local cache = common.localcache():get("headerunit_objectfiles") or {} +function _add_objectfile_to_link_arguments(target, objectfile) + local cachekey = target:name() .. "headerunit_objectfiles" + local cache = common.localcache():get(cachekey) or {} if table.contains(cache, objectfile) then return end table.insert(cache, objectfile) - common.localcache():set("headerunit_objectfiles", cache) - common.localcache():save("headerunit_objectfiles") + common.localcache():set(cachekey, cache) + common.localcache():save(cachekey) end -- load module support for the current target @@ -79,9 +85,6 @@ function load(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}) - target:add("cxxflags", {ifcsearchdirflag, path.join(stlcachedir, "experimental")}, {force = true, expand = false}) -- add stdifcdir in case of if the user ask for it if target:values("msvc.modules.stdifcdir") then @@ -99,14 +102,6 @@ function load(target) end end end - - -- add module cachedirs of all dependent targets with modules - -- this target maybe does not contain module files, @see https://github.com/xmake-io/xmake/issues/1858 - local ifcsearchdirflag = get_ifcsearchdirflag(target) - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.modules_cachedir(dep) - target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) - end end -- provide toolchain include dir for stl headerunit when p1689 is not supported @@ -173,6 +168,11 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} for _, headerunit in ipairs(headerunits) do @@ -184,18 +184,17 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, if not common.localcache():get2(headerunit.name, "building") then common.localcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) common.localcache():set2(headerunit.name, "building", false) end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - end, {rootjob = opt.rootjob}) - _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) - _add_objectfile_to_link_arguments(objectfile) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name .. "=" .. path.translate(bmifile)) + end, {rootjob = flushjob}) + _add_objectfile_to_link_arguments(target, objectfile) end end - _flush_mapflags_to_mapper() end -- generate target stl header units for batchcmds @@ -219,18 +218,18 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) local objectfile = bmifile .. ".obj" if not os.isfile(bmifile) or not os.isfile(objectfile) then - local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) - _add_objectfile_to_link_arguments(objectfile) + _add_objectfile_to_link_arguments(target, objectfile) end + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name .. "=" .. path.translate(bmifile)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- generate target user header units for batchcmds @@ -247,6 +246,11 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -282,11 +286,10 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - end, {rootjob = opt.rootjob}) - _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) - _add_objectfile_to_link_arguments(objectfile) + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.translate(bmifile)) + end, {rootjob = flushjob}) + _add_objectfile_to_link_arguments(target, objectfile) end - _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -329,13 +332,13 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) - _add_objectfile_to_link_arguments(objectfile) + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.translate(bmifile)) + _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper() + _flush_mapflags_to_mapper(target) end -- build module files for batchjobs @@ -350,6 +353,11 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_modules", function(index, total) + _flush_mapflags_to_mapper(target) + end, {rootjob = opt.rootjob}) + -- build modules local common_args = {"-TP"} local provided_modules = {} @@ -380,30 +388,40 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- append module mapper flags first -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper if not target:data("cxx.add_modules_mapflags") then - local mapflags = _get_mapflags_from_mapper() + -- append target module mapper flags + local mapflags = _get_mapflags_from_mapper(target) if mapflags then target:add("cxxflags", mapflags, {force = true}) end + + -- append deps module mapper flags + for _, dep in ipairs(target:orderdeps()) do + local mapflags = _get_mapflags_from_mapper(dep) + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + end + target:data_set("cxx.add_modules_mapflags", true) end local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + local flag = name .. "=" .. path.translate(bmifile) + _add_module_to_mapper(target, referenceflag, flag) + target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) end) if m.requires then moduleinfo.deps = table.keys(m.requires) end moduleinfo.name = name provided_modules[name] = moduleinfo - _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) target:add("objectfiles", objectfile) end end - _flush_mapflags_to_mapper() - -- build batchjobs for modules - common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) + common.build_batchjobs_for_modules(provided_modules, batchjobs, flushjob) end -- build module files for batchcmds @@ -418,35 +436,23 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- we need update mapper first - 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!") - end - end - - local bmifile = provide.bmi - _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) - target:add("objectfiles", objectfile) - end - end - _flush_mapflags_to_mapper() + -- make sure mapper is flushed + _flush_mapflags_to_mapper(target) - -- append module mapper flags - local mapflags = _get_mapflags_from_mapper() + -- append target module mapper flags + local mapflags = _get_mapflags_from_mapper(target) if mapflags then target:add("cxxflags", mapflags, {force = true}) end + -- append deps module mapper flags + for _, dep in ipairs(target:orderdeps()) do + local mapflags = _get_mapflags_from_mapper(dep) + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + end + -- build modules local common_args = {"-TP"} local depmtime = 0 @@ -466,10 +472,14 @@ 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_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) + local flag = name .. "=" .. bmifile + _add_module_to_mapper(target, referenceflag, flag) + target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) depmtime = math.max(depmtime, os.mtime(bmifile)) end end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper(target) end function get_bmi_extension() -- cgit v1.3.1 From eb4dcb38f468d93cac4e471bce246eea6601ecea Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 12:42:25 +0200 Subject: don't rebuild headerunits build by other targets --- xmake/rules/c++/modules/modules_support/clang.lua | 48 +++++++++++++++++------ xmake/rules/c++/modules/modules_support/msvc.lua | 31 ++++++++++----- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 2d6840f28..9c8ac3ac0 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -32,12 +32,23 @@ import("common") -- e.g -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- -function _add_module_to_mapper(target, bmi) +function _add_module_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s", modulefileflag, bmi) - if table.contains(mapflags, mapflag) then - return + local mapflag = format("%s%s=%s", modulefileflag, name, bmi) + local tosearch = format("%s%s=", modulefileflag, name) + for _, line in ipairs(mapflags) do + if line:startswith(tosearch) then + return + end + end + for _, dep in ipairs(target:orderdeps()) do + local mapflags = _get_mapflags_from_mapper(dep) + for _, line in ipairs(mapflags_) do + if line:startswith(tosearch) then + return + end + end end table.insert(mapflags, mapflag) common.localcache():set2(_mapper_cachekey(target), mapflags) @@ -50,14 +61,25 @@ end -- add a header unit into the mapper -- -- e.g --- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm +-- -fmodule-file=foo.hpp=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- -function _add_headerunit_to_mapper(target, bmi) +function _add_headerunit_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s", modulefileflag, bmi) - if table.contains(mapflags, mapflag) then - return + local mapflag = format("%s%s=%s", modulefileflag, bmi) + local tosearch = format("%s%s=", modulefileflag, name) + for _, line in ipairs(mapflags) do + if line:startswith(tosearch) then + return + end + end + for _, dep in ipairs(target:orderdeps()) do + local mapflags = _get_mapflags_from_mapper(dep) + for _, line in ipairs(mapflags_) do + if line:startswith(tosearch) then + return + end + end end table.insert(mapflags, mapflag) common.localcache():set(_mapper_cachekey(target), mapflags) @@ -412,8 +434,8 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) - _add_module_to_mapper(target, bmifile) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) + _add_module_to_mapper(target, name, bmifile) + target:add("cxxflags", modulefileflag .. name .. "=" .. bmifile, {force = true}) end) if m.requires then moduleinfo.deps = table.keys(m.requires) @@ -469,8 +491,8 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(target, bmifile) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) + _add_module_to_mapper(target, headerunit.name, bmifile) + target:add("cxxflags", modulefileflag .. name .. "=" .. bmifile, {force = true}) depmtime = math.max(depmtime, os.mtime(bmifile)) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 46a20993e..5a89af95f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -33,11 +33,22 @@ import("common") -- /headerUnit:angle Foo=build/.gens/Foo/rules/modules/cache/Foo.ifc -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- -function _add_module_to_mapper(target, argument, module) +function _add_module_to_mapper(target, argument, module, bmifile) local mapflags = _get_mapflags_from_mapper(target) - local mapflag = format("%s %s", argument, module) - if table.contains(mapflags, mapflag) then - return + local mapflag = format("%s %s=%s", argument, module, bmifile) + local tosearch = format("%s %s=", argument, module) + for _, line in ipairs(mapflags) do + if line:startswith(tosearch) then + return + end + end + for _, dep in ipairs(target:orderdeps()) do + local mapflags_ = _get_mapflags_from_mapper(dep) + for _, line in ipairs(mapflags_) do + if line:startswith(tosearch) then + return + end + end end table.insert(mapflags, mapflag) common.localcache():set(_mapper_cachekey(target), mapflags) @@ -190,7 +201,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name .. "=" .. path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) end @@ -225,7 +236,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, _add_objectfile_to_link_arguments(target, objectfile) end - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name .. "=" .. path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -285,8 +296,8 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, common.localcache():set2(headerunit.name, "building", false) end + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.translate(bmifile)) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) end @@ -332,7 +343,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -408,7 +419,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) local flag = name .. "=" .. path.translate(bmifile) - _add_module_to_mapper(target, referenceflag, flag) + _add_module_to_mapper(target, referenceflag, name, path.translate(bmifile)) target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) end) if m.requires then @@ -473,7 +484,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) local flag = name .. "=" .. bmifile - _add_module_to_mapper(target, referenceflag, flag) + _add_module_to_mapper(target, referenceflag, name, bmifile) target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) depmtime = math.max(depmtime, os.mtime(bmifile)) end -- cgit v1.3.1 From 4dbf51bde2a49289be217544b8cd38b1ac38b203 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 12:44:12 +0200 Subject: fix headerunits on clang --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 9c8ac3ac0..92ff6548f 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -66,7 +66,7 @@ end function _add_headerunit_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s=%s", modulefileflag, bmi) + local mapflag = format("%s%s=%s", modulefileflag, name, bmi) local tosearch = format("%s%s=", modulefileflag, name) for _, line in ipairs(mapflags) do if line:startswith(tosearch) then -- cgit v1.3.1 From 12b6d0c1611bce8ae73d491bb5f0216f20bc8ffb Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 13:20:33 +0200 Subject: fix clang --- xmake/rules/c++/modules/modules_support/clang.lua | 70 ++++++++--------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 92ff6548f..5d4636502 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -26,8 +26,9 @@ import("core.project.config") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") +import("stl_headers") --- add a module into the mapper +-- add a module or an header unit into the mapper -- -- e.g -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm @@ -35,23 +36,14 @@ import("common") function _add_module_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s=%s", modulefileflag, name, bmi) - local tosearch = format("%s%s=", modulefileflag, name) - for _, line in ipairs(mapflags) do - if line:startswith(tosearch) then - return - end - end - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - for _, line in ipairs(mapflags_) do - if line:startswith(tosearch) then - return - end - end + local mapflag = format("%s%s", modulefileflag, bmi) + local in_mapper = common.localcache():get2("in_mapper", name) + if in_mapper then + mapflag = in_mapper end table.insert(mapflags, mapflag) - common.localcache():set2(_mapper_cachekey(target), mapflags) + common.localcache():set2("in_mapper", name, mapflags) + common.localcache():set(_mapper_cachekey(target), mapflags) end function _mapper_cachekey(target) @@ -66,22 +58,14 @@ end function _add_headerunit_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s=%s", modulefileflag, name, bmi) - local tosearch = format("%s%s=", modulefileflag, name) - for _, line in ipairs(mapflags) do - if line:startswith(tosearch) then - return - end - end - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - for _, line in ipairs(mapflags_) do - if line:startswith(tosearch) then - return - end - end + local mapflag = format("%s%s", modulefileflag, bmi) + local in_mapper = common.localcache():get2("in_mapper", name) + if common.localcache():get2("in_mapper", name) then + mapflag = in_mapper end + table.insert(mapflags, mapflag) + common.localcache():set2("in_mapper", name, mapflags) common.localcache():set(_mapper_cachekey(target), mapflags) end @@ -89,6 +73,7 @@ end function _flush_mapflags_to_mapper(target) -- not using set2/get2 to flush only current target mapper common.localcache():save(_mapper_cachekey(target)) + common.localcache():save("headerunits") end -- get mapflags from mapper @@ -223,12 +208,11 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, bmifile) + _add_headerunit_to_mapper(target, headerunit.name, bmifile) end end, {rootjob = flushjob}) end end - _flush_mapflags_to_mapper(target) end -- generate target stl header units for batchcmds @@ -253,7 +237,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, bmifile) + _add_headerunit_to_mapper(target, headerunit.name, bmifile) end end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -314,10 +298,9 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_headerunit_to_mapper(target, bmifile) + _add_headerunit_to_mapper(target, headerunit.name, bmifile) end, {rootjob = flushjob}) end - _flush_mapflags_to_mapper(target) end -- generate target user header units for batchcmds @@ -361,7 +344,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - _add_headerunit_to_mapper(target, bmifile) + _add_headerunit_to_mapper(target, headerunit.name, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end @@ -417,17 +400,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op if not target:data("cxx.add_modules_mapflags") then -- append module mapper flags local mapflags = _get_mapflags_from_mapper(target) + print(target:name(), mapflags) if mapflags then target:add("cxxflags", mapflags, {force = true}) end - - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - end target:data_set("cxx.add_modules_mapflags", true) end local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} @@ -435,7 +411,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) _add_module_to_mapper(target, name, bmifile) - target:add("cxxflags", modulefileflag .. name .. "=" .. bmifile, {force = true}) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) end) if m.requires then moduleinfo.deps = table.keys(m.requires) @@ -491,8 +467,8 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(target, headerunit.name, bmifile) - target:add("cxxflags", modulefileflag .. name .. "=" .. bmifile, {force = true}) + _add_module_to_mapper(target, name, bmifile) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) depmtime = math.max(depmtime, os.mtime(bmifile)) end end -- cgit v1.3.1 From fa4ada819810fe6b2760e36e6ff7b5f7afe5303d Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Aug 2022 13:43:49 +0200 Subject: fix clang --- xmake/rules/c++/modules/modules_support/clang.lua | 49 ++++++----------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 5d4636502..09fe5119b 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -31,7 +31,9 @@ import("stl_headers") -- add a module or an header unit into the mapper -- -- e.g --- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.pcm +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/iostream.pcm +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- function _add_module_to_mapper(target, name, bmi) local mapflags = _get_mapflags_from_mapper(target) @@ -42,7 +44,7 @@ function _add_module_to_mapper(target, name, bmi) mapflag = in_mapper end table.insert(mapflags, mapflag) - common.localcache():set2("in_mapper", name, mapflags) + common.localcache():set2("in_mapper", name, mapflag) common.localcache():set(_mapper_cachekey(target), mapflags) end @@ -50,30 +52,11 @@ function _mapper_cachekey(target) return target:name() .. "_mapflags" end --- add a header unit into the mapper --- --- e.g --- -fmodule-file=foo.hpp=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm --- -function _add_headerunit_to_mapper(target, name, bmi) - local mapflags = _get_mapflags_from_mapper(target) - local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s", modulefileflag, bmi) - local in_mapper = common.localcache():get2("in_mapper", name) - if common.localcache():get2("in_mapper", name) then - mapflag = in_mapper - end - - table.insert(mapflags, mapflag) - common.localcache():set2("in_mapper", name, mapflags) - common.localcache():set(_mapper_cachekey(target), mapflags) -end - -- flush mapflags to mapper file cache function _flush_mapflags_to_mapper(target) -- not using set2/get2 to flush only current target mapper common.localcache():save(_mapper_cachekey(target)) - common.localcache():save("headerunits") + common.localcache():save("in_mapper") end -- get mapflags from mapper @@ -208,7 +191,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, headerunit.name, bmifile) + _add_module_to_mapper(target, headerunit.name, bmifile) end end, {rootjob = flushjob}) end @@ -237,7 +220,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then - _add_headerunit_to_mapper(target, headerunit.name, bmifile) + _add_module_to_mapper(target, headerunit.name, bmifile) end end depmtime = math.max(depmtime, os.mtime(bmifile)) @@ -298,7 +281,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_headerunit_to_mapper(target, headerunit.name, bmifile) + _add_module_to_mapper(target, headerunit.name, bmifile) end, {rootjob = flushjob}) end end @@ -344,8 +327,8 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) - _add_headerunit_to_mapper(target, headerunit.name, bmifile) - + _add_module_to_mapper(target, headerunit.name, bmifile) + depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -400,7 +383,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op if not target:data("cxx.add_modules_mapflags") then -- append module mapper flags local mapflags = _get_mapflags_from_mapper(target) - print(target:name(), mapflags) if mapflags then target:add("cxxflags", mapflags, {force = true}) end @@ -433,20 +415,15 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + -- ensure mapper is flushed + _flush_mapflags_to_mapper(target) + -- append module mapper flags local mapflags = _get_mapflags_from_mapper(target) if mapflags then target:add("cxxflags", mapflags, {force = true}) end - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - end - -- build modules local depmtime = 0 local common_args = {modulecachepathflag .. cachedir} -- cgit v1.3.1 From f4fda8f0fb19a16a19a1f26e7b7e9d52cc36b1ea Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Aug 2022 16:51:34 +0200 Subject: Improve MSVC --- xmake/rules/c++/modules/modules_support/common.lua | 40 +-- xmake/rules/c++/modules/modules_support/msvc.lua | 323 +++++++++++++-------- 2 files changed, 221 insertions(+), 142 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 96468456f..8072800bc 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -131,7 +131,7 @@ function contains_modules(target) if not target_with_modules then for _, dep in ipairs(target:orderdeps()) do local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then + if sourcebatches["c++.build.modules"] then target_with_modules = true break end @@ -196,24 +196,28 @@ function parse_dependency_data(target, moduleinfos) for _, rule in ipairs(moduleinfo.rules) do modules = modules or {} local m = {} - for _, provide in ipairs(rule.provides) do - m.provides = m.provides or {} - assert(provide["logical-name"]) - if provide["compiled-module-path"] then - if not path.is_absolute(provide["compiled-module-path"]) then - m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) + if rule.provides then + for _, provide in ipairs(rule.provides) do + m.provides = m.provides or {} + assert(provide["logical-name"]) + if provide["compiled-module-path"] then + if not path.is_absolute(provide["compiled-module-path"]) then + m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) + else + m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) + end else - m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) + -- assume path with name + local name = provide["logical-name"] .. bmi_extension(target) + name:replace(":", "-") + m.provides[provide["logical-name"]] = { + bmi = path.join(cachedir, name), + sourcefile = moduleinfo.sourcefile + } end - else - -- assume path with name - local name = provide["logical-name"] .. bmi_extension(target) - name:replace(":", "-") - m.provides[provide["logical-name"]] = { - bmi = path.join(cachedir, name), - sourcefile = moduleinfo.sourcefile - } end + else + m.cppfile = moduleinfo.sourcefile end assert(rule["primary-output"]) modules[path.translate(rule["primary-output"])] = m @@ -527,9 +531,9 @@ function append_headerunits_objectfiles(target) local cache = localcache():get(cachekey) or {} if target:is_binary() then target:add("ldflags", cache, {force = true}) - elseif target:is_static() == "static" then + elseif target:is_static() then target:add("arflags", cache, {force = true}) - elseif target:is_shared() == "shared" then + elseif target:is_shared() then target:add("shflags", cache, {force = true}) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 5a89af95f..68f75444e 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -23,6 +23,7 @@ import("core.tool.compiler") import("core.project.project") import("core.project.depend") import("core.project.config") +import("core.base.hashset") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") @@ -33,40 +34,46 @@ import("common") -- /headerUnit:angle Foo=build/.gens/Foo/rules/modules/cache/Foo.ifc -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- -function _add_module_to_mapper(target, argument, module, bmifile) - local mapflags = _get_mapflags_from_mapper(target) - local mapflag = format("%s %s=%s", argument, module, bmifile) - local tosearch = format("%s %s=", argument, module) - for _, line in ipairs(mapflags) do - if line:startswith(tosearch) then - return - end +function _add_module_to_mapper(target, argument, name, bmifile, deps) + local modulemap = _get_modulemap_from_mapper(target) + local mapflag = {argument, name .. "=" .. bmifile} + + if modulemap[name] then + return end - for _, dep in ipairs(target:orderdeps()) do - local mapflags_ = _get_mapflags_from_mapper(dep) - for _, line in ipairs(mapflags_) do - if line:startswith(tosearch) then - return + + for _, t in ipairs(project:targets()) do + if not t:name() == target:name() then + local t_modulemap = _get_modulemap_from_mapper(t) + if t_modulemap[name] then + mapflag = t_modulemap[name].flag + break end end end - table.insert(mapflags, mapflag) - common.localcache():set(_mapper_cachekey(target), mapflags) + + modulemap[name] = {flag = mapflag, deps = deps} + common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end function _mapper_cachekey(target) - return target:name() .. "_mapflags" + return target:name() .. "_modulemap" end --- flush mapflags to mapper file cache -function _flush_mapflags_to_mapper(target) +-- flush mapper file cache +function _flush_mapper(target) -- not using set2/get2 to flush only current target mapper common.localcache():save(_mapper_cachekey(target)) end --- get mapflags from mapper -function _get_mapflags_from_mapper(target) - return common.localcache():get(_mapper_cachekey(target)) or {} +-- get modulemap from mapper +function _get_modulemap_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulemap") or {} +end + +-- get modulenames from mapper +function _get_modulenames_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulenames") or {} end -- add an objectfile to the linker args @@ -181,7 +188,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, -- flush job local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits @@ -192,16 +199,16 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, if not os.isfile(bmifile) or not os.isfile(objectfile) then batchjobs:addjob(headerunit.name, function(index, total) depend.on_changed(function() - if not common.localcache():get2(headerunit.name, "building") then - common.localcache():set2(headerunit.name, "building", true) + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - common.localcache():set2(headerunit.name, "building", false) end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) end @@ -228,19 +235,20 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) local objectfile = bmifile .. ".obj" - if not os.isfile(bmifile) or not os.isfile(objectfile) then + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - - _add_objectfile_to_link_arguments(target, objectfile) end - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- generate target user header units for batchcmds @@ -259,7 +267,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- flush job local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits @@ -279,8 +287,8 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local bmifile = path.join(outputdir, bmifilename) batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() - if not common.localcache():get2(headerunit.name, "building") then - common.localcache():set2(headerunit.name, "building", true) + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local objectdir = path.directory(objectfile) if not os.isdir(objectdir) then @@ -293,10 +301,9 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- generate headerunit local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - common.localcache():set2(headerunit.name, "building", false) end + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) @@ -343,13 +350,13 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- build module files for batchjobs @@ -366,73 +373,96 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- flush job local flushjob = batchjobs:addjob(target:name() .. "_modules", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) - -- build modules local common_args = {"-TP"} - local provided_modules = {} + local modulesjobs = {} + local cpp_modules = {} 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!") + local module = modules[objectfile] + if module then + if module.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(module.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) - depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) - local objectdir = path.directory(objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) - end + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) -- append module mapper flags first - -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper - if not target:data("cxx.add_modules_mapflags") then - -- append target module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) + + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) + end end + end - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + end) + if module.requires then + moduleinfo.deps = table.keys(module.requires) + end + moduleinfo.name = name + modulesjobs[name] = moduleinfo + target:add("objectfiles", objectfile) + else + if module.requires then + local moduleinfo = {} + moduleinfo.name = module.cppfile + moduleinfo.deps = table.keys(module.requires) + moduleinfo.sourcefile = module.cppfile + moduleinfo.job = batchjobs:newjob(module.cppfile, function(index, total) + function contains(t, v) + for _, flag in pairs(t) do + if table.contains(flag, v) then + return true + end end + return false end - - target:data_set("cxx.add_modules_mapflags", true) - end - local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) - local flag = name .. "=" .. path.translate(bmifile) - _add_module_to_mapper(target, referenceflag, name, path.translate(bmifile)) - target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) - end) - if m.requires then - moduleinfo.deps = table.keys(m.requires) + -- append module mapper flags + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags_ = get_requiresflags(target, module.requires) + local flags = {} + for i=1, #flags_, 2 do + if not contains(flags, flags_[i + 1]) then + table.insert(flags, {flags_[i], flags_[i + 1]}) + end + end + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end) + modulesjobs[moduleinfo.name] = moduleinfo + end end - moduleinfo.name = name - provided_modules[name] = moduleinfo - target:add("objectfiles", objectfile) end end -- build batchjobs for modules - common.build_batchjobs_for_modules(provided_modules, batchjobs, flushjob) + common.build_batchjobs_for_modules(modulesjobs, batchjobs, flushjob) end -- build module files for batchcmds @@ -447,50 +477,64 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- make sure mapper is flushed - _flush_mapflags_to_mapper(target) - - -- append target module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - end -- build modules local common_args = {"-TP"} local depmtime = 0 + local requiresflags for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - if m and m.provides then - local name, provide - for k, v in pairs(m.provides) do - name = k - provide = v - break - end + local module = modules[objectfile] + if module then + if module.provides then + local name, provide + for k, v in pairs(module.provides) do + name = k + provide = v + break + end - local bmifile = provide.bmi - local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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), {envs = vcvars}) - batchcmds:add_depfiles(provide.sourcefile) - local flag = name .. "=" .. bmifile - _add_module_to_mapper(target, referenceflag, name, bmifile) - target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) - depmtime = math.max(depmtime, os.mtime(bmifile)) + -- append required modulemap flags to module + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) + + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) + end + end + end + + local bmifile = provide.bmi + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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, flags or {}, args), {envs = vcvars}) + batchcmds:add_depfiles(provide.sourcefile) + _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + depmtime = math.max(depmtime, os.mtime(bmifile)) + else + if module.requires then + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) + + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) + end + end + end + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end + end end end + batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end function get_bmi_extension() @@ -634,3 +678,34 @@ function get_scandependenciesflag(target) end return scandependenciesflag or nil end + +function get_requiresflags(target, requires) + local flags = {} + local modulemap = _get_modulemap_from_mapper(target) + -- add deps required module flags + for name, required in pairs(requires) do + for _, dep in ipairs(target:orderdeps()) do + local modulemap_ = _get_modulemap_from_mapper(dep) + if modulemap_[name] then + table.join2(flags, modulemap_[name].flag) + table.join2(flags, modulemap_[name].deps or {}) + goto CONTINUE + else + print(modulemap) + end + end + + -- append target required module mapper flags + if modulemap[name] then + table.join2(flags, modulemap[name].flag) + table.join2(flags, modulemap[name].deps or {}) + goto CONTINUE + end + + assert(false, "Missing dependency " .. name .. " for " .. target:name()) + + + ::CONTINUE:: + end + return flags +end \ No newline at end of file -- cgit v1.3.1 From 334a540681025ad0d71fc5f390252c4879593858 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Aug 2022 00:44:42 +0800 Subject: improve fileconfig_add --- xmake/core/project/target.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index faf11b3cc..190cb5887 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1286,10 +1286,24 @@ function _instance:fileconfig_add(sourcefile, info) local fileconfig = filesconfig[sourcefile] if fileconfig then for k, v in pairs(info) do - if fileconfig[k] then - fileconfig[k] = table.join(fileconfig[k], v) + if k == "force" then + -- fileconfig_add("xxx.c", {force = {cxxflags = ""}}) + local force = fileconfig[k] or {} + for k2, v2 in pairs(v) do + if force[k2] then + force[k2] = table.join(force[k2], v2) + else + force[k2] = v2 + end + end + fileconfig[k] = force else - fileconfig[k] = v + -- fileconfig_add("xxx.c", {cxxflags = ""}) + if fileconfig[k] then + fileconfig[k] = table.join(fileconfig[k], v) + else + fileconfig[k] = v + end end end else -- cgit v1.3.1 From e0ef30091d40acb97d4ce6435903915d58777848 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Aug 2022 20:40:53 +0200 Subject: fix msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 52 +++++++++++------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 68f75444e..b1fc871cb 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -431,31 +431,31 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) else if module.requires then - local moduleinfo = {} - moduleinfo.name = module.cppfile - moduleinfo.deps = table.keys(module.requires) - moduleinfo.sourcefile = module.cppfile - moduleinfo.job = batchjobs:newjob(module.cppfile, function(index, total) - function contains(t, v) - for _, flag in pairs(t) do - if table.contains(flag, v) then - return true + modulesjobs[module.cppfile] = { + name = module.cppfile, + deps = table.keys(module.requires), + sourcefile = module.cppfile, + job = batchjobs:newjob(module.cppfile, function(index, total) + function contains(t, v) + for _, flag in pairs(t) do + if table.contains(flag, v) then + return true + end end + return false end - return false - end - -- append module mapper flags - -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper - local flags_ = get_requiresflags(target, module.requires) - local flags = {} - for i=1, #flags_, 2 do - if not contains(flags, flags_[i + 1]) then - table.insert(flags, {flags_[i], flags_[i + 1]}) + -- append module mapper flags + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags_ = get_requiresflags(target, module.requires) + local flags = {} + for i=1, #flags_, 2 do + if not contains(flags, flags_[i + 1]) then + table.insert(flags, {flags_[i], flags_[i + 1]}) + end end - end - target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) - end) - modulesjobs[moduleinfo.name] = moduleinfo + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end) + } end end end @@ -481,7 +481,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- build modules local common_args = {"-TP"} local depmtime = 0 - local requiresflags for _, objectfile in ipairs(objectfiles) do local module = modules[objectfile] if module then @@ -523,7 +522,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op flags = flags or {} for i=1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then - table.join2(flags, {flags_[i], flags_[i + 1]}) + table.insert(flags, {flags_[i], flags_[i + 1]}) end end end @@ -690,8 +689,6 @@ function get_requiresflags(target, requires) table.join2(flags, modulemap_[name].flag) table.join2(flags, modulemap_[name].deps or {}) goto CONTINUE - else - print(modulemap) end end @@ -702,8 +699,7 @@ function get_requiresflags(target, requires) goto CONTINUE end - assert(false, "Missing dependency " .. name .. " for " .. target:name()) - + --assert(false, "Missing dependency " .. name .. " for " .. target:name()) ::CONTINUE:: end -- cgit v1.3.1 From 5619e35bf4c683d43af0008685ca38f15b07e728 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Aug 2022 20:50:59 +0200 Subject: remove unused vars --- xmake/rules/c++/modules/modules_support/msvc.lua | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b1fc871cb..c76034620 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -71,11 +71,6 @@ function _get_modulemap_from_mapper(target) return common.localcache():get2(_mapper_cachekey(target), "modulemap") or {} end --- get modulenames from mapper -function _get_modulenames_from_mapper(target) - return common.localcache():get2(_mapper_cachekey(target), "modulenames") or {} -end - -- add an objectfile to the linker args -- -- e.g @@ -94,12 +89,8 @@ end -- load module support for the current target function load(target) - local cachedir = common.modules_cachedir(target) - local stlcachedir = common.stlmodules_cachedir(target) - -- get flags local modulesflag = get_modulesflag(target) - local ifcsearchdirflag = get_ifcsearchdirflag(target) -- add modules flags target:add("cxxflags", modulesflag) @@ -364,7 +355,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - local cachedir = common.modules_cachedir(target) -- get flags local ifcoutputflag = get_ifcoutputflag(target) @@ -378,7 +368,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local common_args = {"-TP"} local modulesjobs = {} - local cpp_modules = {} for _, objectfile in ipairs(objectfiles) do local module = modules[objectfile] if module then -- cgit v1.3.1 From 1cba4c5ea43adb3bd622f2dd8ca763fb3d793dfe Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Aug 2022 20:51:09 +0200 Subject: improve clang --- xmake/rules/c++/modules/modules_support/clang.lua | 289 +++++++++++++--------- xmake/rules/c++/modules/modules_support/msvc.lua | 2 +- 2 files changed, 178 insertions(+), 113 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 09fe5119b..a1ccc654b 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -36,39 +36,45 @@ import("stl_headers") -- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- function _add_module_to_mapper(target, name, bmi) - local mapflags = _get_mapflags_from_mapper(target) local modulefileflag = get_modulefileflag(target) - local mapflag = format("%s%s", modulefileflag, bmi) - local in_mapper = common.localcache():get2("in_mapper", name) - if in_mapper then - mapflag = in_mapper + local modulemap = _get_modulemap_from_mapper(target) or {} + local mapflag = format("%s%s", modulefileflag, bmifile) + + if modulemap[name] then + return end - table.insert(mapflags, mapflag) - common.localcache():set2("in_mapper", name, mapflag) - common.localcache():set(_mapper_cachekey(target), mapflags) + + for _, t in ipairs(project:targets()) do + if not t:name() == target:name() then + local t_modulemap = _get_modulemap_from_mapper(t) + if t_modulemap[name] then + mapflag = t_modulemap[name].flag + break + end + end + end + + modulemap[name] = {flag = mapflag, deps = deps} + common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end function _mapper_cachekey(target) - return target:name() .. "_mapflags" + return target:name() .. "_modulemap" end --- flush mapflags to mapper file cache -function _flush_mapflags_to_mapper(target) +-- flush modulemap to mapper file cache +function _flush_mapper(target) -- not using set2/get2 to flush only current target mapper common.localcache():save(_mapper_cachekey(target)) - common.localcache():save("in_mapper") end --- get mapflags from mapper -function _get_mapflags_from_mapper(target) - return common.localcache():get(_mapper_cachekey(target)) or {} +-- get modulemap from mapper +function _get_modulemap_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulemap") end -- load module support for the current target function load(target) - local cachedir = common.modules_cachedir(target) - local stlcachedir = common.stlmodules_cachedir(target) - -- get module and module cache flags local modulesflag = get_modulesflag(target) local builtinmodulemapflag = get_builtinmodulemapflag(target) @@ -169,24 +175,26 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local compinst = target:compiler("cxx") local stlcachedir = common.stlmodules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local modulefileflag = get_modulefileflag(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- flush job local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits - local projectdir = os.projectdir() for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) - local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) -- libc++ have a builtin module mapper @@ -205,7 +213,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local modulefileflag = get_modulefileflag(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- build headerunits @@ -213,20 +220,21 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) - if not os.isfile(bmifile) then + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - - -- libc++ have a builtin module mapper - if not target:data_set("cxx.modules.use_libc++") then - _add_module_to_mapper(target, headerunit.name, bmifile) - end + end + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_module_to_mapper(target, headerunit.name, bmifile) end depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- generate target user header units for batchjobs @@ -237,16 +245,13 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local modulefileflag = get_modulefileflag(target) -- flush job local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits - local objectfiles = {} - local flags = {} local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) @@ -294,11 +299,8 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) - local modulefileflag = get_modulefileflag(target) -- build headerunits - local objectfiles = {} - local flags = {} local projectdir = os.projectdir() local depmtime = 0 for _, headerunit in ipairs(headerunits) do @@ -327,12 +329,13 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) batchcmds:add_depfiles(headerunit.path) + _add_module_to_mapper(target, headerunit.name, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- build module files for batchjobs @@ -344,68 +347,90 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- flush job local flushjob = batchjobs:addjob(target:name() .. "_stl_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build modules local common_args = {modulecachepathflag .. cachedir} - 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!") + local module = modules[objectfile] + if module then + if module.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(module.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) - depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) - local bmidir = path.directory(bmifile) - if not os.isdir(bmidir) then - os.mkdir(bmidir) - end - local objectdir = path.directory(objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) - end + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) -- append module mapper flags first - -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper - if not target:data("cxx.add_modules_mapflags") then - -- append module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - target:data_set("cxx.add_modules_mapflags", true) + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags + if module.requires then + local flags = get_requiresflags(target, module.requires) + flags = table.unique(flags) end - local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) - end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) - _add_module_to_mapper(target, name, bmifile) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) - end) - if m.requires then - moduleinfo.deps = table.keys(m.requires) + + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local bmidir = path.directory(bmifile) + if not os.isdir(bmidir) then + os.mkdir(bmidir) + end + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, args)) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + _add_module_to_mapper(target, name, bmifile, flags) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) + end) + if module.requires then + moduleinfo.deps = table.keys(module.requires) + end + moduleinfo.name = name + 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) + function contains(t, v) + for _, flag in pairs(t) do + if table.contains(flag, v) then + return true + end + end + return false + end + -- append module mapper flags + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags = get_requiresflags(target, module.requires) + target:fileconfig_add(module.cppfile, {force = {cxxflags = table.unique(flags or {})}}) + end) + } + end end - moduleinfo.name = name - provided_modules[name] = moduleinfo - target:add("objectfiles", objectfile) end end -- build batchjobs for modules - common.build_batchjobs_for_modules(provided_modules, batchjobs, flushjob) + common.build_batchjobs_for_modules(modulesjobs, batchjobs, flushjob) end -- build module files for batchcmds @@ -415,42 +440,54 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) - -- ensure mapper is flushed - _flush_mapflags_to_mapper(target) + -- make sure mapper is flushed + _flush_mapper(target) -- append module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) + local modulemap = _get_modulemap_from_mapper(target) + if modulemap then + target:add("cxxflags", modulemap, {force = true}) end -- build modules local depmtime = 0 local common_args = {modulecachepathflag .. cachedir} for _, objectfile in ipairs(objectfiles) do - local m = modules[objectfile] - if m and m.provides then - local name, provide - for k, v in pairs(m.provides) do - name = k - provide = v - break + local module = modules[objectfile] + if module then + if module.provides then + local name, provide + for k, v in pairs(module.provides) do + name = k + provide = v + break + end + local bmifile = provide.bmi + local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } + local flags + if module.requires then + local flags = get_requiresflags(target, module.requires) + flags = table.unique(flags) + end + 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, flags or {}, args)) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) + batchcmds:add_depfiles(provide.sourcefile) + _add_module_to_mapper(target, name, bmifile) + target:add("cxxflags", modulefileflag .. bmifile, {force = true}) + depmtime = math.max(depmtime, os.mtime(bmifile)) + else + if module.requires then + local flags = get_requiresflags(target, module.requires) + flags = table.unique(flags) + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end end - local bmifile = provide.bmi - local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } - batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) - batchcmds:mkdir(path.directory(bmifile)) - batchcmds:mkdir(path.directory(objectfile)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) - batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(target, name, bmifile) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) - depmtime = math.max(depmtime, os.mtime(bmifile)) end end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end function get_bmi_extension() @@ -565,3 +602,31 @@ function has_headerunitsupport(target) end return support_headerunits or nil end + +function get_requiresflags(target, requires) + local flags = {} + local modulemap = _get_modulemap_from_mapper(target) + -- add deps required module flags + for name, _ in pairs(requires) do + for _, dep in ipairs(target:orderdeps()) do + local modulemap_ = _get_modulemap_from_mapper(dep) + if modulemap_[name] then + table.join2(flags, modulemap_[name].flag) + table.join2(flags, modulemap_[name].deps or {}) + goto CONTINUE + end + end + + -- append target required module mapper flags + if modulemap[name] then + table.join2(flags, modulemap[name].flag) + table.join2(flags, modulemap[name].deps or {}) + goto CONTINUE + end + + --assert(false, "Missing dependency " .. name .. " for " .. target:name()) + + ::CONTINUE:: + end + return flags +end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index c76034620..fe17265de 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -671,7 +671,7 @@ function get_requiresflags(target, requires) local flags = {} local modulemap = _get_modulemap_from_mapper(target) -- add deps required module flags - for name, required in pairs(requires) do + for name, _ in pairs(requires) do for _, dep in ipairs(target:orderdeps()) do local modulemap_ = _get_modulemap_from_mapper(dep) if modulemap_[name] then -- cgit v1.3.1 From 81eda42b114a53bce7f2d627c90c8f5697b93a80 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Aug 2022 23:04:44 +0200 Subject: improve code --- xmake/rules/c++/modules/modules_support/clang.lua | 43 ++++++++--------------- xmake/rules/c++/modules/modules_support/msvc.lua | 38 ++++++++++---------- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index a1ccc654b..a42912586 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -35,26 +35,22 @@ import("stl_headers") -- -fmodule-file=build/.gens/Foo/rules/modules/cache/iostream.pcm -- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- -function _add_module_to_mapper(target, name, bmi) +function _add_module_to_mapper(target, name, bmifile, deps) local modulefileflag = get_modulefileflag(target) - local modulemap = _get_modulemap_from_mapper(target) or {} + local modulemap = _get_modulemap_from_mapper(target) local mapflag = format("%s%s", modulefileflag, bmifile) - if modulemap[name] then return end - for _, t in ipairs(project:targets()) do - if not t:name() == target:name() then - local t_modulemap = _get_modulemap_from_mapper(t) - if t_modulemap[name] then - mapflag = t_modulemap[name].flag - break - end + if not project.targets()[target:name()] then + local t_modulemap = _get_modulemap_from_mapper(t) + if t_modulemap[name] then + mapflag = t_modulemap[name].flag end end - modulemap[name] = {flag = mapflag, deps = deps} + modulemap[name] = {flag = mapflag, deps = deps} common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end @@ -70,7 +66,7 @@ end -- get modulemap from mapper function _get_modulemap_from_mapper(target) - return common.localcache():get2(_mapper_cachekey(target), "modulemap") + return common.localcache():get2(_mapper_cachekey(target), "modulemap") or {} end -- load module support for the current target @@ -129,7 +125,7 @@ function toolchain_includedirs(target) local _, result = try {function () return os.iorunv(clang, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do - line = line:trim() + line = line:trim() if os.isdir(line) then table.insert(includedirs, path.normalize(line)) elseif line:startswith("End") then @@ -376,7 +372,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper local flags if module.requires then - local flags = get_requiresflags(target, module.requires) + flags = get_requiresflags(target, module.requires) flags = table.unique(flags) end @@ -440,15 +436,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) - -- make sure mapper is flushed - _flush_mapper(target) - - -- append module mapper flags - local modulemap = _get_modulemap_from_mapper(target) - if modulemap then - target:add("cxxflags", modulemap, {force = true}) - end - -- build modules local depmtime = 0 local common_args = {modulecachepathflag .. cachedir} @@ -466,7 +453,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } local flags if module.requires then - local flags = get_requiresflags(target, module.requires) + flags = get_requiresflags(target, module.requires) flags = table.unique(flags) end batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -613,7 +600,7 @@ function get_requiresflags(target, requires) if modulemap_[name] then table.join2(flags, modulemap_[name].flag) table.join2(flags, modulemap_[name].deps or {}) - goto CONTINUE + goto continue end end @@ -621,12 +608,10 @@ function get_requiresflags(target, requires) if modulemap[name] then table.join2(flags, modulemap[name].flag) table.join2(flags, modulemap[name].deps or {}) - goto CONTINUE + goto continue end - --assert(false, "Missing dependency " .. name .. " for " .. target:name()) - - ::CONTINUE:: + ::continue:: end return flags end \ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index fe17265de..d3554106f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -37,22 +37,18 @@ import("common") function _add_module_to_mapper(target, argument, name, bmifile, deps) local modulemap = _get_modulemap_from_mapper(target) local mapflag = {argument, name .. "=" .. bmifile} - if modulemap[name] then return end - for _, t in ipairs(project:targets()) do - if not t:name() == target:name() then - local t_modulemap = _get_modulemap_from_mapper(t) - if t_modulemap[name] then - mapflag = t_modulemap[name].flag - break - end + if not project.targets()[target:name()] then + local t_modulemap = _get_modulemap_from_mapper(t) + if t_modulemap[name] then + mapflag = t_modulemap[name].flag end end - modulemap[name] = {flag = mapflag, deps = deps} + modulemap[name] = {flag = mapflag, deps = deps} common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end @@ -200,8 +196,10 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end end, {rootjob = flushjob}) - _add_objectfile_to_link_arguments(target, objectfile) end end end @@ -235,7 +233,9 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:add_depfiles(headerunit.path) end _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) - _add_objectfile_to_link_arguments(target, objectfile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -294,10 +294,12 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = flushjob}) - _add_objectfile_to_link_arguments(target, objectfile) end end @@ -466,7 +468,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- build modules local common_args = {"-TP"} local depmtime = 0 @@ -487,7 +488,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local flags_ = get_requiresflags(target, module.requires) flags = flags or {} - for i=1, #flags_, 2 do + for i=2, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then table.join2(flags, {flags_[i], flags_[i + 1]}) end @@ -507,7 +508,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local flags if module.requires then local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} for i=1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then @@ -677,7 +677,7 @@ function get_requiresflags(target, requires) if modulemap_[name] then table.join2(flags, modulemap_[name].flag) table.join2(flags, modulemap_[name].deps or {}) - goto CONTINUE + goto continue end end @@ -685,12 +685,10 @@ function get_requiresflags(target, requires) if modulemap[name] then table.join2(flags, modulemap[name].flag) table.join2(flags, modulemap[name].deps or {}) - goto CONTINUE + goto continue end - --assert(false, "Missing dependency " .. name .. " for " .. target:name()) - - ::CONTINUE:: + ::continue:: end return flags end \ No newline at end of file -- cgit v1.3.1 From 9d0aee83336d769c9c2fc0f74b35e183a2e59fcf Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 11 Aug 2022 13:40:21 +0200 Subject: code style --- xmake/rules/c++/modules/modules_support/msvc.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index d3554106f..2f50a485f 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -396,7 +396,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local flags_ = get_requiresflags(target, module.requires) flags = flags or {} - for i=1, #flags_, 2 do + for i = 1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then table.join2(flags, {flags_[i], flags_[i + 1]}) end @@ -439,7 +439,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper local flags_ = get_requiresflags(target, module.requires) local flags = {} - for i=1, #flags_, 2 do + for i = 1, #flags_, 2 do if not contains(flags, flags_[i + 1]) then table.insert(flags, {flags_[i], flags_[i + 1]}) end @@ -488,7 +488,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local flags_ = get_requiresflags(target, module.requires) flags = flags or {} - for i=2, #flags_, 2 do + for i = 1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then table.join2(flags, {flags_[i], flags_[i + 1]}) end @@ -509,7 +509,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op if module.requires then local flags_ = get_requiresflags(target, module.requires) flags = flags or {} - for i=1, #flags_, 2 do + for i = 1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then table.insert(flags, {flags_[i], flags_[i + 1]}) end -- cgit v1.3.1 From 5e0358b48a64ca871165be09d2d9d23b77849879 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 11 Aug 2022 18:34:34 +0200 Subject: fix user_headerunit link test --- tests/projects/c++/modules/user_headerunit/src/header.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/c++/modules/user_headerunit/src/header.hpp b/tests/projects/c++/modules/user_headerunit/src/header.hpp index 15e522e15..840c3da80 100644 --- a/tests/projects/c++/modules/user_headerunit/src/header.hpp +++ b/tests/projects/c++/modules/user_headerunit/src/header.hpp @@ -1,5 +1,5 @@ #pragma once namespace hello { - extern constexpr auto FOO = "Hello"; + constexpr auto FOO = "Hello"; } -- cgit v1.3.1 From 2723282a4fd0af130ac5d65c5b40fa12f7ce803f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 12 Aug 2022 22:32:57 +0800 Subject: improve tests for cxxmodules --- tests/projects/c++/modules/stl_headerunit/test.lua | 1 + tests/projects/c++/modules/test_base.lua | 15 ++++++++-- tests/projects/c++/modules/test_headerunits.lua | 34 ++++++++++++++++++++++ .../projects/c++/modules/user_headerunit/test.lua | 1 + 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/projects/c++/modules/stl_headerunit/test.lua create mode 100644 tests/projects/c++/modules/test_headerunits.lua create mode 100644 tests/projects/c++/modules/user_headerunit/test.lua diff --git a/tests/projects/c++/modules/stl_headerunit/test.lua b/tests/projects/c++/modules/stl_headerunit/test.lua new file mode 100644 index 000000000..c18e5a1d0 --- /dev/null +++ b/tests/projects/c++/modules/stl_headerunit/test.lua @@ -0,0 +1 @@ +inherit(".test_headerunits") diff --git a/tests/projects/c++/modules/test_base.lua b/tests/projects/c++/modules/test_base.lua index 68efbeaa0..4aee9f8e7 100644 --- a/tests/projects/c++/modules/test_base.lua +++ b/tests/projects/c++/modules/test_base.lua @@ -1,21 +1,30 @@ import("lib.detect.find_tool") import("core.base.semver") +function _build() + local ci = (os.getenv("CI") or os.getenv("GITHUB_ACTIONS") or ""):lower() + if ci == "true" then + os.exec("xmake -rvD") + else + os.exec("xmake -r") + end +end + function main(t) if is_subhost("windows") then os.exec("xmake f -c") - os.exec("xmake -r") + _build() elseif is_host("linux") then local gcc = find_tool("gcc", {version = true}) if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then os.exec("xmake f -c") - os.exec("xmake -r") + _build() end local clang = find_tool("clang", {version = true}) if clang and clang.version and semver.compare(clang.version, "14.0") >= 0 then os.exec("xmake clean -a") os.exec("xmake f --toolchain=clang -c") - os.exec("xmake -r") + _build() end end end diff --git a/tests/projects/c++/modules/test_headerunits.lua b/tests/projects/c++/modules/test_headerunits.lua new file mode 100644 index 000000000..905812c14 --- /dev/null +++ b/tests/projects/c++/modules/test_headerunits.lua @@ -0,0 +1,34 @@ +import("lib.detect.find_tool") +import("core.base.semver") +import("detect.sdks.find_vstudio") + +function _build() + local ci = (os.getenv("CI") or os.getenv("GITHUB_ACTIONS") or ""):lower() + if ci == "true" then + os.exec("xmake -rvD") + else + os.exec("xmake -r") + end +end + +function main(t) + if is_subhost("windows") then + local vs = find_vstudio() + if vs and vs["2022"] then + os.exec("xmake f -c") + _build() + end + elseif is_host("linux") then + local gcc = find_tool("gcc", {version = true}) + if gcc and gcc.version and semver.compare(gcc.version, "11.0") >= 0 then + os.exec("xmake f -c") + _build() + end + local clang = find_tool("clang", {version = true}) + if clang and clang.version and semver.compare(clang.version, "16.0") >= 0 then + os.exec("xmake clean -a") + os.exec("xmake f --toolchain=clang -c") + _build() + end + end +end diff --git a/tests/projects/c++/modules/user_headerunit/test.lua b/tests/projects/c++/modules/user_headerunit/test.lua new file mode 100644 index 000000000..c18e5a1d0 --- /dev/null +++ b/tests/projects/c++/modules/user_headerunit/test.lua @@ -0,0 +1 @@ +inherit(".test_headerunits") -- cgit v1.3.1 From 8dccc2d987d20b6df18360adab034ebd42f6ec9b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 12 Aug 2022 22:49:52 +0800 Subject: Update common.lua --- xmake/rules/c++/modules/modules_support/common.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 8072800bc..39ad17f2e 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -125,6 +125,17 @@ function bmi_extension(target) return modules_support(target).get_bmi_extension() end +-- has module extension? e.g. *.mpp, ... +function has_module_extension(sourcefile) + local modulexts = _g.modulexts + if modulexts == nil then + modulexts = hashset.of(".mpp", ".mxx", ".cppm", ".ixx") + _g.modulexts = modulexts + end + local extension = path.extension(sourcefile) + return modulexts:has(extension:lower()) +end + -- this target contains module files? function contains_modules(target) local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false @@ -377,6 +388,11 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) module_name = line:match("export%s+module%s+(.+)%s*;") end local module_depname = line:match("import%s+(.+)%s*;") + -- we need parse module interface dep in cxx/impl_unit.cpp, e.g. hello.mpp and hello_impl.cpp + -- @see https://github.com/xmake-io/xmake/pull/2664#issuecomment-1213167314 + if not module_depname and not has_module_extension(sourcefile) then + module_depname = line:match("module%s+(.+)%s*;") + end if module_depname then local module_dep = {} -- partition? import :xxx; -- cgit v1.3.1 From 26fd967f81b4ab03ae2e04310545725729be8e63 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 09:39:39 +0800 Subject: remove tailing spaces --- xmake/rules/c++/modules/modules_support/clang.lua | 16 ++++++++-------- xmake/rules/c++/modules/modules_support/msvc.lua | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index a42912586..b68355b8c 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -125,7 +125,7 @@ function toolchain_includedirs(target) local _, result = try {function () return os.iorunv(clang, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do - line = line:trim() + line = line:trim() if os.isdir(line) then table.insert(includedirs, path.normalize(line)) elseif line:startswith("End") then @@ -185,13 +185,13 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() -- don't build same header unit at the same time - if not common.memcache():get2(headerunit.name, "building") then + if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) -- libc++ have a builtin module mapper if not target:data_set("cxx.modules.use_libc++") then @@ -217,7 +217,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) -- don't build same header unit at the same time - if not common.memcache():get2(headerunit.name, "building") then + if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -327,7 +327,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:add_depfiles(headerunit.path) _add_module_to_mapper(target, headerunit.name, bmifile) - + depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) @@ -405,7 +405,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op name = module.cppfile, deps = table.keys(module.requires), sourcefile = module.cppfile, - job = batchjobs:newjob(module.cppfile, function(index, total) + job = batchjobs:newjob(module.cppfile, function(index, total) function contains(t, v) for _, flag in pairs(t) do if table.contains(flag, v) then @@ -595,7 +595,7 @@ function get_requiresflags(target, requires) local modulemap = _get_modulemap_from_mapper(target) -- add deps required module flags for name, _ in pairs(requires) do - for _, dep in ipairs(target:orderdeps()) do + for _, dep in ipairs(target:orderdeps()) do local modulemap_ = _get_modulemap_from_mapper(dep) if modulemap_[name] then table.join2(flags, modulemap_[name].flag) @@ -614,4 +614,4 @@ function get_requiresflags(target, requires) ::continue:: end return flags -end \ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 2f50a485f..13de1a7b8 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -187,7 +187,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, batchjobs:addjob(headerunit.name, function(index, total) depend.on_changed(function() -- don't build same header unit at the same time - if not common.memcache():get2(headerunit.name, "building") then + if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} @@ -225,7 +225,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) local objectfile = bmifile .. ".obj" -- don't build same header unit at the same time - if not common.memcache():get2(headerunit.name, "building") then + if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) @@ -278,7 +278,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local bmifile = path.join(outputdir, bmifilename) batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() - if not common.memcache():get2(headerunit.name, "building") then + if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local objectdir = path.directory(objectfile) @@ -426,7 +426,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op name = module.cppfile, deps = table.keys(module.requires), sourcefile = module.cppfile, - job = batchjobs:newjob(module.cppfile, function(index, total) + job = batchjobs:newjob(module.cppfile, function(index, total) function contains(t, v) for _, flag in pairs(t) do if table.contains(flag, v) then @@ -672,7 +672,7 @@ function get_requiresflags(target, requires) local modulemap = _get_modulemap_from_mapper(target) -- add deps required module flags for name, _ in pairs(requires) do - for _, dep in ipairs(target:orderdeps()) do + for _, dep in ipairs(target:orderdeps()) do local modulemap_ = _get_modulemap_from_mapper(dep) if modulemap_[name] then table.join2(flags, modulemap_[name].flag) @@ -691,4 +691,4 @@ function get_requiresflags(target, requires) ::continue:: end return flags -end \ No newline at end of file +end -- cgit v1.3.1 From 6da269d62f704e47a292aea6fddd23e4dd6e582d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 10:00:14 +0800 Subject: improve msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 30 ++++++++---------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 13de1a7b8..a53748baa 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -36,18 +36,10 @@ import("common") -- function _add_module_to_mapper(target, argument, name, bmifile, deps) local modulemap = _get_modulemap_from_mapper(target) - local mapflag = {argument, name .. "=" .. bmifile} if modulemap[name] then return end - - if not project.targets()[target:name()] then - local t_modulemap = _get_modulemap_from_mapper(t) - if t_modulemap[name] then - mapflag = t_modulemap[name].flag - end - end - + local mapflag = {argument, name .. "=" .. bmifile} modulemap[name] = {flag = mapflag, deps = deps} common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end @@ -185,7 +177,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local objectfile = bmifile .. ".obj" if not os.isfile(bmifile) or not os.isfile(objectfile) then batchjobs:addjob(headerunit.name, function(index, total) - depend.on_changed(function() + depend.on_changed(function() -- don't build same header unit at the same time if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) @@ -194,8 +186,8 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end - end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) if os.isfile(objectfile) then _add_objectfile_to_link_arguments(target, objectfile) end @@ -293,11 +285,10 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) end - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) - if os.isfile(objectfile) then - _add_objectfile_to_link_arguments(target, objectfile) - end - + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = flushjob}) end @@ -394,7 +385,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local flags if module.requires then local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} for i = 1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then @@ -428,7 +418,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op sourcefile = module.cppfile, job = batchjobs:newjob(module.cppfile, function(index, total) function contains(t, v) - for _, flag in pairs(t) do + for _, flag in ipairs(t) do if table.contains(flag, v) then return true end @@ -486,7 +476,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local flags if module.requires then local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} for i = 1, #flags_, 2 do if not table.contains(flags, flags_[i + 1]) then @@ -667,6 +656,7 @@ function get_scandependenciesflag(target) return scandependenciesflag or nil end +-- get requireflags from module mapper function get_requiresflags(target, requires) local flags = {} local modulemap = _get_modulemap_from_mapper(target) -- cgit v1.3.1 From c0120aaf7781407a1cf2d87451dbcdf39f7a3db2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 10:06:16 +0800 Subject: improve clang --- xmake/rules/c++/modules/modules_support/clang.lua | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index b68355b8c..c6e6de6af 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -36,20 +36,13 @@ import("stl_headers") -- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- function _add_module_to_mapper(target, name, bmifile, deps) - local modulefileflag = get_modulefileflag(target) local modulemap = _get_modulemap_from_mapper(target) - local mapflag = format("%s%s", modulefileflag, bmifile) if modulemap[name] then return end - if not project.targets()[target:name()] then - local t_modulemap = _get_modulemap_from_mapper(t) - if t_modulemap[name] then - mapflag = t_modulemap[name].flag - end - end - + local modulefileflag = get_modulefileflag(target) + local mapflag = format("%s%s", modulefileflag, bmifile) modulemap[name] = {flag = mapflag, deps = deps} common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end @@ -205,8 +198,6 @@ end -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") - - -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) local modulecachepathflag = get_modulecachepathflag(target) assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") @@ -391,7 +382,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) _add_module_to_mapper(target, name, bmifile, flags) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) end) if module.requires then moduleinfo.deps = table.keys(module.requires) @@ -462,7 +452,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) _add_module_to_mapper(target, name, bmifile) - target:add("cxxflags", modulefileflag .. bmifile, {force = true}) depmtime = math.max(depmtime, os.mtime(bmifile)) else if module.requires then -- cgit v1.3.1 From a8829eee52be60f9ee7cf3b29ea03c42bd6c986e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 10:27:24 +0800 Subject: disable bpf test for arch --- tests/projects/linux/bpf/minimal/test.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/projects/linux/bpf/minimal/test.lua b/tests/projects/linux/bpf/minimal/test.lua index 2856a3831..474060ab0 100644 --- a/tests/projects/linux/bpf/minimal/test.lua +++ b/tests/projects/linux/bpf/minimal/test.lua @@ -1,5 +1,9 @@ function main(t) if is_host("linux") and os.arch() == "x86_64" then + -- TODO, we need wait fix of linux kernel + if linuxos.name() == "archlinux" then + return + end os.vrun("xmake f -y -p android -vD") os.vrun("xmake -y -vD") end -- cgit v1.3.1 From 85759892a32f733dd5d368f17547a65501dce88f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 10:55:47 +0800 Subject: improve requriesflags --- xmake/rules/c++/modules/modules_support/clang.lua | 45 +++++++--------- xmake/rules/c++/modules/modules_support/msvc.lua | 66 ++++++++++------------- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index c6e6de6af..bd4448ae7 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -361,10 +361,9 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) -- append module mapper flags first -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper - local flags + local requiresflags if module.requires then - flags = get_requiresflags(target, module.requires) - flags = table.unique(flags) + requiresflags = get_requiresflags(target, module.requires) end depend.on_changed(function() @@ -378,10 +377,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.mkdir(objectdir) end local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, args)) - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, args)) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, {bmifile}, {"-c", "-o", objectfile})) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) - _add_module_to_mapper(target, name, bmifile, flags) + _add_module_to_mapper(target, name, bmifile, requiresflags) end) if module.requires then moduleinfo.deps = table.keys(module.requires) @@ -396,18 +395,12 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op deps = table.keys(module.requires), sourcefile = module.cppfile, job = batchjobs:newjob(module.cppfile, function(index, total) - function contains(t, v) - for _, flag in pairs(t) do - if table.contains(flag, v) then - return true - end - end - return false - end -- append module mapper flags -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper - local flags = get_requiresflags(target, module.requires) - target:fileconfig_add(module.cppfile, {force = {cxxflags = table.unique(flags or {})}}) + local requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) + end end) } end @@ -441,23 +434,23 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } - local flags + local requiresflags if module.requires then - flags = get_requiresflags(target, module.requires) - flags = table.unique(flags) + requiresflags = get_requiresflags(target, module.requires) end 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, flags or {}, args)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, {bmifile}, {"-c", "-o", objectfile})) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, args)) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) _add_module_to_mapper(target, name, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) else if module.requires then - local flags = get_requiresflags(target, module.requires) - flags = table.unique(flags) - target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + local requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) + end end end end @@ -602,5 +595,7 @@ function get_requiresflags(target, requires) ::continue:: end - return flags + if #flags > 0 then + return table.unique(flags) + end end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index a53748baa..d09275e9d 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -382,17 +382,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) -- append module mapper flags first -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper - local flags + local requiresflags if module.requires then - local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} - for i = 1, #flags_, 2 do - if not table.contains(flags, flags_[i + 1]) then - table.join2(flags, {flags_[i], flags_[i + 1]}) - end - end + requiresflags = get_requiresflags(target, module.requires) end - depend.on_changed(function() progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) local objectdir = path.directory(objectfile) @@ -400,9 +393,9 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op os.mkdir(objectdir) end local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} - os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, flags or {}, args), {envs = vcvars}) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, args), {envs = vcvars}) end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) - _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + _add_module_to_mapper(target, referenceflag, name, bmifile, requiresflags) end) if module.requires then moduleinfo.deps = table.keys(module.requires) @@ -427,14 +420,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op end -- append module mapper flags -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper - local flags_ = get_requiresflags(target, module.requires) - local flags = {} - for i = 1, #flags_, 2 do - if not contains(flags, flags_[i + 1]) then - table.insert(flags, {flags_[i], flags_[i + 1]}) - end + local requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) end - target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) end) } end @@ -473,38 +462,25 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end -- append required modulemap flags to module - local flags + local requiresflags if module.requires then - local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} - for i = 1, #flags_, 2 do - if not table.contains(flags, flags_[i + 1]) then - table.join2(flags, {flags_[i], flags_[i + 1]}) - end - end + requiresflags = get_requiresflags(target, module.requires) end local bmifile = provide.bmi local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, 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, flags or {}, args), {envs = vcvars}) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + _add_module_to_mapper(target, referenceflag, name, bmifile, requiresflags) depmtime = math.max(depmtime, os.mtime(bmifile)) else if module.requires then - local flags - if module.requires then - local flags_ = get_requiresflags(target, module.requires) - flags = flags or {} - for i = 1, #flags_, 2 do - if not table.contains(flags, flags_[i + 1]) then - table.insert(flags, {flags_[i], flags_[i + 1]}) - end - end + local requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) end - target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) end end end @@ -680,5 +656,17 @@ function get_requiresflags(target, requires) ::continue:: end - return flags + local requireflags = {} + local contains = {} + for i = 1, #flags, 2 do + local value = flags[i + 1] + if not contains[value] then + local key = flags[i] + table.insert(requireflags, {key, value}) + contains[value] = true + end + end + if #requireflags > 0 then + return requireflags + end end -- cgit v1.3.1 From 595a078ba33abd374cf900a07570222151caf605 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 11:33:18 +0800 Subject: expand requires flags --- xmake/rules/c++/modules/modules_support/msvc.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index d09275e9d..4f7c8edc2 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -384,7 +384,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper local requiresflags if module.requires then - requiresflags = get_requiresflags(target, module.requires) + requiresflags = get_requiresflags(target, module.requires, {expand = true}) end depend.on_changed(function() progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) @@ -464,7 +464,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- append required modulemap flags to module local requiresflags if module.requires then - requiresflags = get_requiresflags(target, module.requires) + requiresflags = get_requiresflags(target, module.requires, {expand = true}) end local bmifile = provide.bmi @@ -633,7 +633,8 @@ function get_scandependenciesflag(target) end -- get requireflags from module mapper -function get_requiresflags(target, requires) +function get_requiresflags(target, requires, opt) + opt = opt or {} local flags = {} local modulemap = _get_modulemap_from_mapper(target) -- add deps required module flags @@ -662,7 +663,12 @@ function get_requiresflags(target, requires) local value = flags[i + 1] if not contains[value] then local key = flags[i] - table.insert(requireflags, {key, value}) + if opt.expand then + table.insert(requireflags, key) + table.insert(requireflags, value) + else + table.insert(requireflags, {key, value}) + end contains[value] = true end end -- cgit v1.3.1 From 740b0d520e5718464df394ed5b6f4e51aa834818 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 11:56:43 +0800 Subject: improve generator --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index bd4448ae7..a29a56db7 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -433,7 +433,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op break end local bmifile = provide.bmi - local args = { "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } + local args = {"-c", "-x", "c++-module", "--precompile", path(provide.sourcefile), "-o", path(bmifile)} local requiresflags if module.requires then requiresflags = get_requiresflags(target, module.requires) @@ -441,7 +441,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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, requiresflags or {}, args)) - batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, {bmifile}, {"-c", "-o", objectfile})) + batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, requiresflags or {}, path(bmifile), {"-c", "-o", path(objectfile)})) batchcmds:add_depfiles(provide.sourcefile) _add_module_to_mapper(target, name, bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) -- cgit v1.3.1 From e75f37dd0829ca2351bbc78d47f992e1f691cc53 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 12:01:17 +0800 Subject: translate more paths --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index a29a56db7..1a3b0ee80 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -210,7 +210,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- don't build same header unit at the same time if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) - local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", path(bmifile), "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end @@ -308,7 +308,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local args = { modulecachepathflag .. cachedir, "-c", "-o", bmifile} if headerunit.type == ":quote" then - table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) + table.join2(args, {"-I", path(headerunit.path):directory(), "-x", "c++-user-header", path(headerunit.path)}) elseif headerunit.type == ":angle" then table.join2(args, {"-x", "c++-system-header", headerunit.name}) end -- cgit v1.3.1 From ceee3b9f38385d3093aba79852a10f8affe6f0b6 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Aug 2022 22:38:41 +0800 Subject: translate path --- xmake/rules/c++/modules/modules_support/gcc.lua | 10 +++++----- xmake/rules/c++/modules/modules_support/msvc.lua | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index a37346bad..1405d1cfa 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -189,7 +189,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then - local args = { "-c", "-x", "c++-system-header", headerunit.name } + local args = {"-c", "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end @@ -276,13 +276,13 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) - local args = { "-c" } + local args = {"-c"} local headerunit_path if headerunit.type == ":quote" then - table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) + table.join2(args, {"-I", path(path.relative(headerunit.path, projectdir)):directory(), "-x", "c++-user-header", headerunit.name}) headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) elseif headerunit.type == ":angle" then - table.join2(args, { "-x", "c++-system-header", headerunit.name }) + table.join2(args, {"-x", "c++-system-header", headerunit.name}) -- if path is relative then its a subtarget path headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) end @@ -375,7 +375,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - local args = {"-o", objectfile, "-c", provide.sourcefile} + 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)) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 4f7c8edc2..5214f12df 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -219,7 +219,12 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- don't build same header unit at the same time if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) - local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} + local args = { + headernameflag .. ":angle", + headerunit.name, + ifcoutputflag, + path(headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir), + path(objectfile, function (p) return "-Fo" .. p end)} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) @@ -468,7 +473,12 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + local args = {"-c", + path(objectfile, function (p) return "-Fo" .. p end), + interfaceflag, + ifcoutputflag, + path(bmifile), + 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, requiresflags or {}, args), {envs = vcvars}) -- cgit v1.3.1 From 63bdc1bfaff58ba837e325574c6aa5a8151c8ba8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 10:58:07 +0800 Subject: remove unused code --- xmake/rules/c++/modules/modules_support/common.lua | 5 ++--- xmake/rules/c++/modules/xmake.lua | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 39ad17f2e..0bd1e20d8 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -88,7 +88,6 @@ end -- patch sourcebatch function patch_sourcebatch(target, sourcebatch) - local cachedir = modules_cachedir(target) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = {} sourcebatch.dependfiles = {} @@ -138,11 +137,11 @@ end -- this target contains module files? function contains_modules(target) - local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false + local target_with_modules = target:sourcebatches()["c++.build.modules.builder"] and true or false if not target_with_modules then for _, dep in ipairs(target:orderdeps()) do local sourcebatches = dep:sourcebatches() - if sourcebatches["c++.build.modules"] then + if sourcebatches["c++.build.modules.builder"] then target_with_modules = true break end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 276566a27..ae81ebc25 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -20,8 +20,6 @@ -- define rule: c++.build.modules rule("c++.build.modules") - set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - add_deps("c++.build.modules.builder") add_deps("c++.build.modules.install") -- cgit v1.3.1 From 4560a3458148449eaa959a8a3a62e2c63cfaabba Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 11:09:52 +0800 Subject: remove repeat for compile_commands --- xmake/plugins/project/clang/compile_commands.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 15cbcfeb9..3e00db6f6 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -111,6 +111,15 @@ function _make_arguments(jsonfile, arguments, sourcefile) table.insert(arguments_escape, _escape_path(arg)) end + -- remove repeat + -- this is because some rules will repeatedly bind the same sourcekind, e.g. `rule("c++.build.modules.builder")` + local key = hash.uuid(os.args(arguments_escape) .. sourcefile) + local map = _g.map or {} + _g.map = map + if map[key] then + return + end + -- make body jsonfile:printf( [[%s{ @@ -121,6 +130,7 @@ function _make_arguments(jsonfile, arguments, sourcefile) -- clear first line marks _g.firstline = false + map[key] = true end -- make commands for target -- cgit v1.3.1 From 077fc878bc8da7804cf36765bf54c687dc95f61d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 11:30:28 +0800 Subject: improve cmakelist generator --- xmake/plugins/project/cmake/cmakelists.lua | 12 +++++++----- xmake/plugins/project/make/makefile.lua | 14 +++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 09feb78e3..24d78d209 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -212,13 +212,14 @@ function _add_target_sources(cmakelists, target, outputdir) local has_cuda = false cmakelists:print("target_sources(%s PRIVATE", target:name()) for _, sourcebatch in table.orderpairs(target:sourcebatches()) do - local sourcekind = sourcebatch.sourcekind - if sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "as" or sourcekind == "cu" then + -- we can only use rulename to filter them because sourcekind may be bound to multiple rules + local rulename = sourcebatch.rulename + if rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do cmakelists:print(" " .. _get_unix_path(sourcefile, outputdir)) end end - if sourcekind == "cu" then + if sourcebatch.sourcekind == "cu" then has_cuda = true end end @@ -830,8 +831,9 @@ end function _add_target_custom_commands(cmakelists, target, outputdir) _add_target_custom_commands_for_target(cmakelists, target, outputdir, "before") for _, sourcebatch in table.orderpairs(target:sourcebatches()) do - local sourcekind = sourcebatch.sourcekind - if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then + -- we can only use rulename to filter them because sourcekind may be bound to multiple rules + local rulename = sourcebatch.rulename + if rulename ~= "c++.build" and rulename ~= "asm.build" and rulename ~= "cuda.build" then _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir, "before") _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir) _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir, "after") diff --git a/xmake/plugins/project/make/makefile.lua b/xmake/plugins/project/make/makefile.lua index 7b0ec8f60..87c3b6f55 100644 --- a/xmake/plugins/project/make/makefile.lua +++ b/xmake/plugins/project/make/makefile.lua @@ -192,10 +192,18 @@ end -- make objects function _make_objects(makefile, target, sourcekind, sourcebatch, sourceflags) - - -- make them + local handled_objects = target:data("makefile.handled_objects") + if not handled_objects then + handled_objects = {} + target:data_set("makefile.handled_objects", handled_objects) + end for index, objectfile in ipairs(sourcebatch.objectfiles) do - _make_object(makefile, target, sourcebatch.sourcefiles[index], objectfile, sourceflags) + -- remove repeat + -- this is because some rules will repeatedly bind the same sourcekind, e.g. `rule("c++.build.modules.builder")` + if not handled_objects[objectfile] then + _make_object(makefile, target, sourcebatch.sourcefiles[index], objectfile, sourceflags) + handled_objects[objectfile] = true + end end end -- cgit v1.3.1 From 7553abdc8062e4ae45604e03b05986e84221b33c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 11:43:00 +0800 Subject: translate clang path --- xmake/rules/c++/modules/modules_support/clang.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 1a3b0ee80..fb3a2d1fa 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -210,7 +210,9 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- don't build same header unit at the same time if not common.memcache():get2(headerunit.name, "building") then common.memcache():set2(headerunit.name, "building", true) - local args = {modulecachepathflag .. stlcachedir, "-c", "-o", path(bmifile), "-x", "c++-system-header", headerunit.name} + local args = { + path(stlcachedir, function (p) return modulecachepathflag .. p end), + "-c", "-o", path(bmifile), "-x", "c++-system-header", headerunit.name} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end @@ -306,7 +308,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) - local args = { modulecachepathflag .. cachedir, "-c", "-o", bmifile} + local args = {path(cachedir, function (p) return modulecachepathflag .. p end), "-c", "-o", path(bmifile)} if headerunit.type == ":quote" then table.join2(args, {"-I", path(headerunit.path):directory(), "-x", "c++-user-header", path(headerunit.path)}) elseif headerunit.type == ":angle" then @@ -421,7 +423,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- build modules local depmtime = 0 - local common_args = {modulecachepathflag .. cachedir} + local common_args = {path(cachedir, function (p) return modulecachepathflag .. p end)} for _, objectfile in ipairs(objectfiles) do local module = modules[objectfile] if module then -- cgit v1.3.1 From cbf9452ce0bf312b6ddcc4ab4bcdf61553100a3c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 11:52:39 +0800 Subject: fix modules --- xmake/rules/c++/modules/modules_support/common.lua | 5 +++-- xmake/rules/c++/modules/xmake.lua | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 0bd1e20d8..aa7c0fb59 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -137,11 +137,12 @@ end -- this target contains module files? function contains_modules(target) - local target_with_modules = target:sourcebatches()["c++.build.modules.builder"] and true or false + -- we can not use `"c++.build.modules.builder"`, because it contains sourcekind/cxx. + local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false if not target_with_modules then for _, dep in ipairs(target:orderdeps()) do local sourcebatches = dep:sourcebatches() - if sourcebatches["c++.build.modules.builder"] then + if sourcebatches["c++.build.modules"] then target_with_modules = true break end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index ae81ebc25..3ef960d7a 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -20,6 +20,7 @@ -- define rule: c++.build.modules rule("c++.build.modules") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx") add_deps("c++.build.modules.builder") add_deps("c++.build.modules.install") -- cgit v1.3.1 From dc58599ef5524ab5bd54126b992a3b2d19be0d30 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 21:26:02 +0800 Subject: improve cmakelists --- .../projects/c++/modules/dependence/CMakeLists.txt | 64 ++++++++-- xmake/plugins/project/cmake/cmakelists.lua | 133 +++++++++++++++++---- 2 files changed, 163 insertions(+), 34 deletions(-) diff --git a/tests/projects/c++/modules/dependence/CMakeLists.txt b/tests/projects/c++/modules/dependence/CMakeLists.txt index 19eb7793a..fe09acca6 100644 --- a/tests/projects/c++/modules/dependence/CMakeLists.txt +++ b/tests/projects/c++/modules/dependence/CMakeLists.txt @@ -10,16 +10,60 @@ project(dependence LANGUAGES CXX C) # target add_executable(dependence "") set_target_properties(dependence PROPERTIES OUTPUT_NAME "dependence") -set_target_properties(dependence PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/macosx/x86_64/release") +set_target_properties(dependence PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/linux/x86_64/release") +add_custom_command(OUTPUT output_dependence_932361E8 + COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi mod + VERBATIM +) +add_custom_target(target_dependence_932361E8 + DEPENDS output_dependence_932361E8 +) +add_dependencies(dependence target_dependence_932361E8) +add_custom_command(OUTPUT output_dependence_981BF74C + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src + VERBATIM +) +add_custom_target(target_dependence_981BF74C + DEPENDS output_dependence_981BF74C +) +add_dependencies(dependence target_dependence_981BF74C) +add_custom_command(OUTPUT output_dependence_812F1CA0 + COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/mod.mpp.o -c ${CMAKE_SOURCE_DIR}/src/mod.mpp + VERBATIM +) +add_custom_target(target_dependence_812F1CA0 + DEPENDS output_dependence_812F1CA0 +) +add_dependencies(dependence target_dependence_812F1CA0) +add_custom_command(OUTPUT output_dependence_A56A2AC8 + COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi hello + VERBATIM +) +add_custom_target(target_dependence_A56A2AC8 + DEPENDS output_dependence_A56A2AC8 +) +add_dependencies(dependence target_dependence_A56A2AC8) +add_custom_command(OUTPUT output_dependence_E41992DB + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src + VERBATIM +) +add_custom_target(target_dependence_E41992DB + DEPENDS output_dependence_E41992DB +) +add_dependencies(dependence target_dependence_E41992DB) +add_custom_command(OUTPUT output_dependence_EAE69E5A + COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/hello.mpp.o -c ${CMAKE_SOURCE_DIR}/src/hello.mpp + VERBATIM +) +add_custom_target(target_dependence_EAE69E5A + DEPENDS output_dependence_EAE69E5A +) +add_dependencies(dependence target_dependence_EAE69E5A) target_compile_options(dependence PRIVATE $<$:-m64> $<$:-m64> - $<$:-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk> - $<$:-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk> - $<$:-fmodules> - $<$:-fbuiltin-module-map> - $<$:-fimplicit-modules> - $<$:-fno-implicit-module-maps> + $<$:-fmodules-ts> + $<$:-fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt> ) target_compile_features(dependence PRIVATE cxx_std_20) if(MSVC) @@ -28,16 +72,10 @@ if(MSVC) endif() target_link_options(dependence PRIVATE -m64 - -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk ) target_sources(dependence PRIVATE src/hello_impl.cpp - src/mod_impl.cpp src/main.cpp - src/hello_impl.cpp src/mod_impl.cpp - src/main.cpp - src/mod.mpp - src/hello.mpp ) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 24d78d209..9565bcb40 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -109,6 +109,67 @@ function _get_configs_from_target(target, name) return table.unique(values) end +-- this sourcebatch is built? +function _sourcebatch_is_built(sourcebatch) + -- we can only use rulename to filter them because sourcekind may be bound to multiple rules + local rulename = sourcebatch.rulename + if rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" then + return true + end +end + +-- translate flag +function _translate_flag(flag, outputdir) + if flag then + if path.instance_of(flag) then + flag = flag:clone():set(_get_unix_path_relative_to_cmake(flag:rawstr(), outputdir)):str() + elseif path.is_absolute(flag) then + flag = _get_unix_path_relative_to_cmake(flag, outputdir) + elseif flag:startswith("-fmodule-file=") then + flag = "-fmodule-file=" .. _get_unix_path_relative_to_cmake(flag:sub(15), outputdir) + elseif flag:startswith("-fmodule-mapper=") then + flag = "-fmodule-mapper=" .. _get_unix_path_relative_to_cmake(flag:sub(17), outputdir) + elseif flag:match("(.+)=(.+)") then + local k, v = flag:match("(.+)=(.+)") + if v and v:endswith(".ifc") then -- e.g. hello=xxx/hello.ifc + flag = k .. "=" .. _get_unix_path_relative_to_cmake(v, outputdir) + end + end + end + return flag +end + +-- translate flags +function _translate_flags(flags, outputdir) + if not flags then + return + end + local result = {} + for _, flag in ipairs(flags) do + if type(flag) == "table" and not path.instance_of(flag) then + for _, v in ipairs(flag) do + table.insert(result, _translate_flag(v, outputdir)) + end + else + table.insert(result, _translate_flag(flag, outputdir)) + end + end + return result +end + +-- get flags from fileconfig +function _get_flags_from_fileconfig(fileconfig, outputdir, name) + local flags = {} + table.join2(flags, fileconfig[name]) + if fileconfig.force then + table.join2(flags, fileconfig.force[name]) + end + flags = _translate_flags(flags, outputdir) + if #flags > 0 then + return table.concat(flags, " ") + end +end + -- add project info function _add_project(cmakelists, languages, outputdir) @@ -212,9 +273,7 @@ function _add_target_sources(cmakelists, target, outputdir) local has_cuda = false cmakelists:print("target_sources(%s PRIVATE", target:name()) for _, sourcebatch in table.orderpairs(target:sourcebatches()) do - -- we can only use rulename to filter them because sourcekind may be bound to multiple rules - local rulename = sourcebatch.rulename - if rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" then + if _sourcebatch_is_built(sourcebatch) then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do cmakelists:print(" " .. _get_unix_path(sourcefile, outputdir)) end @@ -392,28 +451,66 @@ function _add_target_compile_definitions(cmakelists, target) end -- add target compile options -function _add_target_compile_options(cmakelists, target) +function _add_target_compile_options(cmakelists, target, outputdir) local cflags = _get_configs_from_target(target, "cflags") local cxflags = _get_configs_from_target(target, "cxflags") local cxxflags = _get_configs_from_target(target, "cxxflags") local cuflags = _get_configs_from_target(target, "cuflags") if #cflags > 0 or #cxflags > 0 or #cxxflags > 0 or #cuflags > 0 then cmakelists:print("target_compile_options(%s PRIVATE", target:name()) - for _, flag in ipairs(cflags) do + for _, flag in ipairs(_translate_flags(cflags, outputdir)) do cmakelists:print(" $<$:" .. flag .. ">") end - for _, flag in ipairs(cxflags) do + for _, flag in ipairs(_translate_flags(cxflags, outputdir)) do cmakelists:print(" $<$:" .. flag .. ">") cmakelists:print(" $<$:" .. flag .. ">") end - for _, flag in ipairs(cxxflags) do + for _, flag in ipairs(_translate_flags(cxxflags, outputdir)) do cmakelists:print(" $<$:" .. flag .. ">") end - for _, flag in ipairs(cuflags) do + for _, flag in ipairs(_translate_flags(cuflags, outputdir)) do cmakelists:print(" $<$:" .. flag .. ">") end cmakelists:print(")") end + + -- add cflags/cxxflags for the specific source files + for _, sourcebatch in table.orderpairs(target:sourcebatches()) do + if _sourcebatch_is_built(sourcebatch) then + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local fileconfig = target:fileconfig(sourcefile) + if fileconfig then + local cxxflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cxxflags") + if cxxflags then + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxxflags .. "\">)") + end + local cflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cflags") + if cflags then + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cflags .. "\">)") + end + local cxflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cxflags") + if cxflags then + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxflags .. "\">)") + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxflags .. "\">)") + end + local cuflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cuflags") + if cuflags then + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cuflags .. "\">)") + end + end + end + end + end end -- add target language standards @@ -700,12 +797,7 @@ function _get_command_string(cmd, outputdir) -- @see https://github.com/xmake-io/xmake/discussions/2156 local argv = {} for _, v in ipairs(cmd.argv) do - if path.instance_of(v) then - v = v:clone():set(_get_unix_path_relative_to_cmake(v:rawstr(), outputdir)):str() - elseif path.is_absolute(v) then - v = _get_unix_path_relative_to_cmake(v, outputdir) - end - table.insert(argv, v) + table.insert(argv, _translate_flag(v, outputdir)) end local command = _get_unix_path_relative_to_cmake(cmd.program) .. " " .. os.args(argv) if opt and opt.curdir then @@ -831,9 +923,7 @@ end function _add_target_custom_commands(cmakelists, target, outputdir) _add_target_custom_commands_for_target(cmakelists, target, outputdir, "before") for _, sourcebatch in table.orderpairs(target:sourcebatches()) do - -- we can only use rulename to filter them because sourcekind may be bound to multiple rules - local rulename = sourcebatch.rulename - if rulename ~= "c++.build" and rulename ~= "asm.build" and rulename ~= "cuda.build" then + if not _sourcebatch_is_built(sourcebatch) then _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir, "before") _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir) _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, outputdir, "after") @@ -887,6 +977,10 @@ function _add_target(cmakelists, target, outputdir) -- add target dependencies _add_target_dependencies(cmakelists, target) + -- add target custom commands + -- we need call it first for running all rules, these rules will change some flags, e.g. c++modules + _add_target_custom_commands(cmakelists, target, outputdir) + -- add target precompilied header _add_target_precompiled_header(cmakelists, target, outputdir) @@ -906,7 +1000,7 @@ function _add_target(cmakelists, target, outputdir) _add_target_language_standards(cmakelists, target) -- add target compile options - _add_target_compile_options(cmakelists, target) + _add_target_compile_options(cmakelists, target, outputdir) -- add target warnings _add_target_warnings(cmakelists, target) @@ -932,9 +1026,6 @@ function _add_target(cmakelists, target, outputdir) -- add target link options _add_target_link_options(cmakelists, target) - -- add target custom commands - _add_target_custom_commands(cmakelists, target, outputdir) - -- add target sources _add_target_sources(cmakelists, target, outputdir) -- cgit v1.3.1 From 44b5b95dd66578f3ea8c14c96bb36dadb5938a8a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 21:43:38 +0800 Subject: optimizate cmakelist --- .../projects/c++/modules/dependence/CMakeLists.txt | 43 ++-------------------- xmake/plugins/project/cmake/cmakelists.lua | 39 +++++++++----------- 2 files changed, 21 insertions(+), 61 deletions(-) diff --git a/tests/projects/c++/modules/dependence/CMakeLists.txt b/tests/projects/c++/modules/dependence/CMakeLists.txt index fe09acca6..4d7715c93 100644 --- a/tests/projects/c++/modules/dependence/CMakeLists.txt +++ b/tests/projects/c++/modules/dependence/CMakeLists.txt @@ -11,54 +11,19 @@ project(dependence LANGUAGES CXX C) add_executable(dependence "") set_target_properties(dependence PROPERTIES OUTPUT_NAME "dependence") set_target_properties(dependence PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/linux/x86_64/release") -add_custom_command(OUTPUT output_dependence_932361E8 +add_custom_command(OUTPUT output_dependence_957D597F COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi mod - VERBATIM -) -add_custom_target(target_dependence_932361E8 - DEPENDS output_dependence_932361E8 -) -add_dependencies(dependence target_dependence_932361E8) -add_custom_command(OUTPUT output_dependence_981BF74C COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src - VERBATIM -) -add_custom_target(target_dependence_981BF74C - DEPENDS output_dependence_981BF74C -) -add_dependencies(dependence target_dependence_981BF74C) -add_custom_command(OUTPUT output_dependence_812F1CA0 COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/mod.mpp.o -c ${CMAKE_SOURCE_DIR}/src/mod.mpp - VERBATIM -) -add_custom_target(target_dependence_812F1CA0 - DEPENDS output_dependence_812F1CA0 -) -add_dependencies(dependence target_dependence_812F1CA0) -add_custom_command(OUTPUT output_dependence_A56A2AC8 COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi hello - VERBATIM -) -add_custom_target(target_dependence_A56A2AC8 - DEPENDS output_dependence_A56A2AC8 -) -add_dependencies(dependence target_dependence_A56A2AC8) -add_custom_command(OUTPUT output_dependence_E41992DB COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src - VERBATIM -) -add_custom_target(target_dependence_E41992DB - DEPENDS output_dependence_E41992DB -) -add_dependencies(dependence target_dependence_E41992DB) -add_custom_command(OUTPUT output_dependence_EAE69E5A COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/hello.mpp.o -c ${CMAKE_SOURCE_DIR}/src/hello.mpp VERBATIM ) -add_custom_target(target_dependence_EAE69E5A - DEPENDS output_dependence_EAE69E5A +add_custom_target(target_dependence_957D597F + DEPENDS output_dependence_957D597F ) -add_dependencies(dependence target_dependence_EAE69E5A) +add_dependencies(dependence target_dependence_957D597F) target_compile_options(dependence PRIVATE $<$:-m64> $<$:-m64> diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 9565bcb40..153e3c4ad 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -826,8 +826,8 @@ function _get_command_string(cmd, outputdir) end end --- add custom command -function _add_target_custom_command(cmakelists, target, command, suffix) +-- add target custom commands for batchcmds +function _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, suffix, batchcmds) if suffix == "before" then -- ADD_CUSTOM_COMMAND and PRE_BUILD did not work as I expected, -- so we need use add_dependencies and fake target to support it. @@ -836,7 +836,12 @@ function _add_target_custom_command(cmakelists, target, command, suffix) -- local key = target:name() .. "_" .. hash.uuid():split("-", {plain = true})[1] cmakelists:print("add_custom_command(OUTPUT output_%s", key) - cmakelists:print(" COMMAND %s", command) + for _, cmd in ipairs(batchcmds:cmds()) do + local command = _get_command_string(cmd, outputdir) + if command then + cmakelists:print(" COMMAND %s", command) + end + end cmakelists:print(" VERBATIM") cmakelists:print(")") cmakelists:print("add_custom_target(target_%s", key) @@ -848,7 +853,12 @@ function _add_target_custom_command(cmakelists, target, command, suffix) if suffix == "after" then cmakelists:print(" POST_BUILD") end - cmakelists:print(" COMMAND %s", command) + for _, cmd in ipairs(batchcmds:cmds()) do + local command = _get_command_string(cmd, outputdir) + if command then + cmakelists:print(" COMMAND %s", command) + end + end cmakelists:print(" VERBATIM") cmakelists:print(")") end @@ -863,12 +873,7 @@ function _add_target_custom_commands_for_target(cmakelists, target, outputdir, s local batchcmds_ = batchcmds.new({target = target}) script(target, batchcmds_, {}) if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd, outputdir) - if command then - _add_target_custom_command(cmakelists, target, command, suffix) - end - end + _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, suffix, batchcmds_) end end end @@ -888,12 +893,7 @@ function _add_target_custom_commands_for_objectrules(cmakelists, target, sourceb local batchcmds_ = batchcmds.new({target = target}) script(target, batchcmds_, sourcebatch, {}) if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd, outputdir) - if command then - _add_target_custom_command(cmakelists, target, command, suffix) - end - end + _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, suffix, batchcmds_) end end @@ -907,12 +907,7 @@ function _add_target_custom_commands_for_objectrules(cmakelists, target, sourceb local batchcmds_ = batchcmds.new({target = target}) script(target, batchcmds_, sourcefile, {}) if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd, outputdir) - if command then - _add_target_custom_command(cmakelists, target, command, suffix) - end - end + _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, suffix, batchcmds_) end end end -- cgit v1.3.1 From d9e3a62bdd4b6390318e0cdebccfe96562c4ef12 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 21:47:07 +0800 Subject: optimizate cmakelist --- .../projects/c++/modules/dependence/CMakeLists.txt | 46 ---------------------- 1 file changed, 46 deletions(-) delete mode 100644 tests/projects/c++/modules/dependence/CMakeLists.txt diff --git a/tests/projects/c++/modules/dependence/CMakeLists.txt b/tests/projects/c++/modules/dependence/CMakeLists.txt deleted file mode 100644 index 4d7715c93..000000000 --- a/tests/projects/c++/modules/dependence/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# this is the build file for project -# it is autogenerated by the xmake build system. -# do not edit by hand. - -# project -cmake_minimum_required(VERSION 3.15.0) -cmake_policy(SET CMP0091 NEW) -project(dependence LANGUAGES CXX C) - -# target -add_executable(dependence "") -set_target_properties(dependence PROPERTIES OUTPUT_NAME "dependence") -set_target_properties(dependence PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/linux/x86_64/release") -add_custom_command(OUTPUT output_dependence_957D597F - COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi mod - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src - COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/mod.mpp.o -c ${CMAKE_SOURCE_DIR}/src/mod.mpp - COMMAND echo ${color.build.progress}[ 0%]:${clear} ${color.build.object}generating.cxx.module.bmi hello - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src - COMMAND /usr/bin/gcc -m64 -std=c++20 -fmodules-ts -fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt -x c++ -o ${CMAKE_SOURCE_DIR}/build/.objs/dependence/linux/x86_64/release/src/hello.mpp.o -c ${CMAKE_SOURCE_DIR}/src/hello.mpp - VERBATIM -) -add_custom_target(target_dependence_957D597F - DEPENDS output_dependence_957D597F -) -add_dependencies(dependence target_dependence_957D597F) -target_compile_options(dependence PRIVATE - $<$:-m64> - $<$:-m64> - $<$:-fmodules-ts> - $<$:-fmodule-mapper=${CMAKE_SOURCE_DIR}/build/mapper.txt> -) -target_compile_features(dependence PRIVATE cxx_std_20) -if(MSVC) - set_property(TARGET dependence PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -endif() -target_link_options(dependence PRIVATE - -m64 -) -target_sources(dependence PRIVATE - src/hello_impl.cpp - src/main.cpp - src/mod_impl.cpp -) - -- cgit v1.3.1 From fcebe80886634ed74bbd1600f175287596528c7f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 22:08:03 +0800 Subject: add objs to cmake link --- xmake/plugins/project/cmake/cmakelists.lua | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 153e3c4ad..16c73e946 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -713,7 +713,7 @@ function _add_target_vs_runtime(cmakelists, target) end -- add target link libraries -function _add_target_link_libraries(cmakelists, target) +function _add_target_link_libraries(cmakelists, target, outputdir) -- add links local links = _get_configs_from_target(target, "links") @@ -732,6 +732,25 @@ function _add_target_link_libraries(cmakelists, target) end cmakelists:print(")") end + + -- add other object files, maybe from custom rules + local objectfiles_set = hashset.new() + for _, sourcebatch in table.orderpairs(target:sourcebatches()) do + if _sourcebatch_is_built(sourcebatch) then + for _, objectfile in ipairs(sourcebatch.objectfiles) do + objectfiles_set:insert(objectfile) + end + end + end + if #target:objectfiles() > objectfiles_set:size() then + cmakelists:print("target_link_libraries(%s PRIVATE", target:name()) + for _, objectfile in ipairs(target:objectfiles()) do + if not objectfiles_set:has(objectfile) then + cmakelists:print(" " .. _get_unix_path_relative_to_cmake(objectfile, outputdir)) + end + end + cmakelists:print(")") + end end -- add target link directories @@ -1013,7 +1032,7 @@ function _add_target(cmakelists, target, outputdir) _add_target_vs_runtime(cmakelists, target) -- add target link libraries - _add_target_link_libraries(cmakelists, target) + _add_target_link_libraries(cmakelists, target, outputdir) -- add target link directories _add_target_link_directories(cmakelists, target, outputdir) -- cgit v1.3.1 From a94e0acf150b96d494c858e07f3ff7d581e3a95e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 23:11:19 +0800 Subject: change toolchain for cmakelist --- xmake/plugins/project/cmake/cmakelists.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 16c73e946..7e5434cc7 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -20,6 +20,7 @@ -- imports import("core.project.project") +import("core.project.config") import("core.tool.compiler") import("core.base.semver") import("core.base.hashset") @@ -224,8 +225,18 @@ function _add_target_phony(cmakelists, target) cmakelists:print("") end +-- set compiler +function _set_target_compiler(cmakelists, target) + -- use custom toolchain? + if config.get("toolchain") or target:get("toolchains") then + cmakelists:print("set(CMAKE_C_COMPILER \"%s\")", target:tool("cc")) + cmakelists:print("set(CMAKE_CXX_COMPILER \"%s\")", target:tool("cxx")) + end +end + -- add target: binary function _add_target_binary(cmakelists, target, outputdir) + _set_target_compiler(cmakelists, target) cmakelists:print("add_executable(%s \"\")", target:name()) cmakelists:print("set_target_properties(%s PROPERTIES OUTPUT_NAME \"%s\")", target:name(), target:basename()) cmakelists:print("set_target_properties(%s PROPERTIES RUNTIME_OUTPUT_DIRECTORY \"%s\")", target:name(), _get_unix_path_relative_to_cmake(target:targetdir(), outputdir)) @@ -233,6 +244,7 @@ end -- add target: static function _add_target_static(cmakelists, target, outputdir) + _set_target_compiler(cmakelists, target) cmakelists:print("add_library(%s STATIC \"\")", target:name()) cmakelists:print("set_target_properties(%s PROPERTIES OUTPUT_NAME \"%s\")", target:name(), target:basename()) cmakelists:print("set_target_properties(%s PROPERTIES ARCHIVE_OUTPUT_DIRECTORY \"%s\")", target:name(), _get_unix_path_relative_to_cmake(target:targetdir(), outputdir)) @@ -240,6 +252,7 @@ end -- add target: shared function _add_target_shared(cmakelists, target, outputdir) + _set_target_compiler(cmakelists, target) cmakelists:print("add_library(%s SHARED \"\")", target:name()) cmakelists:print("set_target_properties(%s PROPERTIES OUTPUT_NAME \"%s\")", target:name(), target:basename()) if target:is_plat("windows") then -- cgit v1.3.1 From d036076ec6ae0b3d374f011db7fb201815f4a386 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 23:22:22 +0800 Subject: improve cmakelsits --- xmake/plugins/project/cmake/cmakelists.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 7e5434cc7..5f6644915 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -497,28 +497,28 @@ function _add_target_compile_options(cmakelists, target, outputdir) if cxxflags then cmakelists:print("set_source_files_properties(" .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxxflags .. "\">)") + .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxxflags .. ">\")") end local cflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cflags") if cflags then cmakelists:print("set_source_files_properties(" .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cflags .. "\">)") + .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cflags .. ">\")") end local cxflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cxflags") if cxflags then cmakelists:print("set_source_files_properties(" .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxflags .. "\">)") + .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxflags .. ">\")") cmakelists:print("set_source_files_properties(" .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cxflags .. "\">)") + .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxflags .. ">\")") end local cuflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cuflags") if cuflags then cmakelists:print("set_source_files_properties(" .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS $<$:\"" .. cuflags .. "\">)") + .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cuflags .. ">\")") end end end -- cgit v1.3.1 From ff971cdfeb55701078e894c380939ed7146b5638 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Aug 2022 23:34:54 +0800 Subject: remove unused stdlang for cmake --- xmake/plugins/project/cmake/cmakelists.lua | 53 ------------------------------ 1 file changed, 53 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 5f6644915..52acbf76f 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -526,56 +526,6 @@ function _add_target_compile_options(cmakelists, target, outputdir) end end --- add target language standards -function _add_target_language_standards(cmakelists, target) - local cstds = - { - c89 = "90" - , gnu89 = "90" -- TODO add cflags -std=gnu90 if supported - , c99 = "99" - , gnu99 = "99" -- TODO - , c11 = "11" - , gnu11 = "11" -- TODO - } - local cxxstds = - { - cxx98 = "98" - , gnuxx98 = "98" -- TODO - , cxx11 = "11" - , gnuxx11 = "11" - , cxx14 = "14" - , gnuxx14 = "14" - , cxx17 = "17" - , gnuxx17 = "17" - , cxx1z = "17" - , gnuxx1z = "17" - , cxx2a = "20" - , gnuxx2a = "20" - , cxxlatest = "latest" - } - for _, lang in ipairs(target:get("languages")) do - local cstd = cstds[lang] - if cstd then - cmakelists:print("set_property(TARGET %s PROPERTY C_STANDARD %s)", target:name(), cstd) - if cstd == "99" or cstd == "11" then - cmakelists:print("if(MSVC)") - cmakelists:print(" target_compile_options(%s PRIVATE $<$:-TP>)", target:name()) - cmakelists:print("endif()") - end - end - local cxxstd = cxxstds[lang] - if cxxstd then - if cxxstd == "latest" then - cmakelists:print("if (MSVC)") - cmakelists:print(" target_compile_options(%s PRIVATE $<$:/std:c++latest>)", target:name()) - cmakelists:print("endif()") - else - cmakelists:print("set_property(TARGET %s PROPERTY CXX_STANDARD %s)", target:name(), cxxstd) - end - end - end -end - -- add target warnings function _add_target_warnings(cmakelists, target) local flags_gcc = @@ -1023,9 +973,6 @@ function _add_target(cmakelists, target, outputdir) -- add target compile definitions _add_target_compile_definitions(cmakelists, target) - -- add target language standards - _add_target_language_standards(cmakelists, target) - -- add target compile options _add_target_compile_options(cmakelists, target, outputdir) -- cgit v1.3.1 From 170b4ff2ddd796c5ed51643690d6a3a141b9caa7 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Aug 2022 23:06:16 +0800 Subject: fix sourcekind for vs generator --- xmake/plugins/project/vstudio/impl/vs201x.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index ce07549c0..dbeb9a9b5 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -283,7 +283,7 @@ function _make_targetinfo(mode, arch, target, vcxprojdir) local sourcekind = sourcebatch.sourcekind if sourcekind then for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do - local compflags = compiler.compflags(sourcefile, {target = target}) + local compflags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) if not firstcompflags and (sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "cu") then firstcompflags = compflags end -- cgit v1.3.1 From bc5a02b3f095d1b749a52d26df183f507f69736c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 00:05:01 +0800 Subject: improve std for cmakelists --- xmake/plugins/project/cmake/cmakelists.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 52acbf76f..3ae159b3d 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -577,8 +577,14 @@ function _add_target_languages(cmakelists, target) local languages = target:get("languages") if languages then for _, lang in ipairs(languages) do + local has_ext = false + if lang:startswith("gnu") then + lang = lang:sub(4) + has_ext = true + end local feature = features[lang] or (features[lang:replace("++", "xx")]) if feature then + cmakelists:print("set_target_properties(%s PROPERTIES CXX_EXTENSIONS %s)", target:name(), has_ext and "ON" or "OFF") cmakelists:print("target_compile_features(%s PRIVATE %s)", target:name(), feature) end end -- cgit v1.3.1 From 594da22d9c682d293ae9563907e9323a64220ff1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 00:16:38 +0800 Subject: improve sourcefiles flags for cmake --- xmake/plugins/project/cmake/cmakelists.lua | 64 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 3ae159b3d..68162e1a5 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -167,7 +167,7 @@ function _get_flags_from_fileconfig(fileconfig, outputdir, name) end flags = _translate_flags(flags, outputdir) if #flags > 0 then - return table.concat(flags, " ") + return flags end end @@ -463,6 +463,34 @@ function _add_target_compile_definitions(cmakelists, target) end end +-- add target source files flags +function _add_target_sourcefiles_flags(cmakelists, target, sourcefile, name, outputdir) + local fileconfig = target:fileconfig(sourcefile) + if fileconfig then + local flags = _get_flags_from_fileconfig(fileconfig, outputdir, name) + if flags and #flags > 0 then + cmakelists:print("set_source_files_properties(" + .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) + .. " PROPERTIES COMPILE_OPTIONS") + local flagstrs = {} + for _, flag in ipairs(flags) do + if name == "cxxflags" then + table.insert(flagstrs, "$<$:" .. flag .. ">") + elseif name == "cflags" then + table.insert(flagstrs, "$<$:" .. flag .. ">") + elseif name == "cxflags" then + table.insert(flagstrs, "$<$:" .. flag .. ">") + table.insert(flagstrs, "$<$:" .. flag .. ">") + elseif name == "cuflags" then + table.insert(flagstrs, "$<$:" .. flag .. ">") + end + end + cmakelists:print(" \"%s\"", table.concat(flagstrs, ";")) + cmakelists:print(")") + end + end +end + -- add target compile options function _add_target_compile_options(cmakelists, target, outputdir) local cflags = _get_configs_from_target(target, "cflags") @@ -491,36 +519,10 @@ function _add_target_compile_options(cmakelists, target, outputdir) for _, sourcebatch in table.orderpairs(target:sourcebatches()) do if _sourcebatch_is_built(sourcebatch) then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local fileconfig = target:fileconfig(sourcefile) - if fileconfig then - local cxxflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cxxflags") - if cxxflags then - cmakelists:print("set_source_files_properties(" - .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxxflags .. ">\")") - end - local cflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cflags") - if cflags then - cmakelists:print("set_source_files_properties(" - .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cflags .. ">\")") - end - local cxflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cxflags") - if cxflags then - cmakelists:print("set_source_files_properties(" - .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxflags .. ">\")") - cmakelists:print("set_source_files_properties(" - .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cxflags .. ">\")") - end - local cuflags = _get_flags_from_fileconfig(fileconfig, outputdir, "cuflags") - if cuflags then - cmakelists:print("set_source_files_properties(" - .. _get_unix_path_relative_to_cmake(sourcefile, outputdir) - .. " PROPERTIES COMPILE_OPTIONS \"$<$:" .. cuflags .. ">\")") - end - end + _add_target_sourcefiles_flags(cmakelists, target, sourcefile, "cxxflags", outputdir) + _add_target_sourcefiles_flags(cmakelists, target, sourcefile, "cflags", outputdir) + _add_target_sourcefiles_flags(cmakelists, target, sourcefile, "cxflags", outputdir) + _add_target_sourcefiles_flags(cmakelists, target, sourcefile, "cuflags", outputdir) end end end -- cgit v1.3.1 From 39981ebf8e9e5cdbe9103c7019957a04485a4444 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 00:18:25 +0800 Subject: improve clang for cmakelists --- xmake/plugins/project/cmake/cmakelists.lua | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 68162e1a5..aae7186a2 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -229,8 +229,24 @@ end function _set_target_compiler(cmakelists, target) -- use custom toolchain? if config.get("toolchain") or target:get("toolchains") then - cmakelists:print("set(CMAKE_C_COMPILER \"%s\")", target:tool("cc")) - cmakelists:print("set(CMAKE_CXX_COMPILER \"%s\")", target:tool("cxx")) + local cc = target:tool("cc") + if cc then + cc = cc:gsub("\\", "/") + cmakelists:print("set(CMAKE_C_COMPILER \"%s\")", cc) + end + local cxx, cxx_name = target:tool("cxx") + if cxx then + if cxx_name == "clang" or cxx_name == "gcc" then + local dir = path.directory(cxx) + local name = path.filename(cxx) + name = name:gsub("clang$", "clang++") + name = name:gsub("clang%-", "clang++-") + name = name:gsub("gcc$", "g++") + name = name:gsub("gcc%-", "g++-") + cxx = path.join(dir, name):gsub("\\", "/") + end + cmakelists:print("set(CMAKE_CXX_COMPILER \"%s\")", cxx) + end end end -- cgit v1.3.1 From 2e502f66692119189c7425a2f7a412942d3a992a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 00:31:24 +0800 Subject: improve cmake and vs generator --- xmake/plugins/project/cmake/cmakelists.lua | 2 +- xmake/plugins/project/vstudio/impl/vs201x.lua | 6 ++++-- .../plugins/project/vstudio/impl/vs201x_vcxproj.lua | 21 ++++++++++++--------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index aae7186a2..130c1ad38 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -114,7 +114,7 @@ end function _sourcebatch_is_built(sourcebatch) -- we can only use rulename to filter them because sourcekind may be bound to multiple rules local rulename = sourcebatch.rulename - if rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" then + if rulename == "c.build" or rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" then return true end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index dbeb9a9b5..ce843d725 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -213,8 +213,9 @@ function _make_custom_commands(target, vcxprojdir) _make_custom_commands_for_target(commands, target, vcxprojdir, "before") _make_custom_commands_for_target(commands, target, vcxprojdir) for _, sourcebatch in pairs(target:sourcebatches()) do + local rulename = sourcebatch.rulename local sourcekind = sourcebatch.sourcekind - if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then + if rulename ~= "c.build" and rulename ~= "c++.build" and rulename ~= "asm.build" and rulename ~= "cuda.build" and sourcekind ~= "mrc" then _make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, "before") _make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, nil) _make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, "after") @@ -281,10 +282,11 @@ function _make_targetinfo(mode, arch, target, vcxprojdir) targetinfo.compargvs = {} for _, sourcebatch in pairs(target:sourcebatches()) do local sourcekind = sourcebatch.sourcekind + local rulename = sourcebatch.rulename if sourcekind then for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do local compflags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) - if not firstcompflags and (sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "cu") then + if not firstcompflags and (rulename == "c.build" or rulename == "c++.build" or rulename == "cuda.build") then firstcompflags = compflags end targetinfo.compflags[sourcefile] = compflags diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 452292abc..f9842bff1 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -713,18 +713,18 @@ function _make_custom_commands_item(vcxprojfile, commands, suffix) vcxprojfile:print("") end vcxprojfile:print("") - vcxprojfile:print("setlocal") + local cmdstr = "setlocal" for _, command in ipairs(commands) do - vcxprojfile:print("%s", command) + cmdstr = cmdstr .. "\n" .. command + cmdstr = cmdstr .. "\nif %errorlevel% neq 0 goto :xmEnd" end - vcxprojfile:write([[if %errorlevel% neq 0 goto :xmEnd -:xmEnd + cmdstr = cmdstr .. "\n" .. [[:xmEnd endlocal & call :xmErrorLevel %errorlevel% & goto :xmDone :xmErrorLevel exit /b %1 :xmDone -if %errorlevel% neq 0 goto :VCEnd -]]) +if %errorlevel% neq 0 goto :VCEnd]] + vcxprojfile:print("%s", cmdstr) if suffix == "after" or suffix == "after_link" then vcxprojfile:print("") elseif suffix == "before" then @@ -957,7 +957,8 @@ function _build_common_items(vsinfo, target) targetinfo.sourceflags = {} for _, sourcebatch in pairs(targetinfo.sourcebatches) do local sourcekind = sourcebatch.sourcekind - if (sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "as" or sourcekind == "mrc") then + local rulename = sourcebatch.rulename + if (rulename == "c.build" or rulename == "c++.build" or rulename == "asm.build" or sourcekind == "mrc") then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do -- make compiler flags @@ -1020,12 +1021,13 @@ function _build_common_items(vsinfo, target) local sourceflags = {} for _, sourcebatch in pairs(targetinfo.sourcebatches) do local sourcekind = sourcebatch.sourcekind + local rulename = sourcebatch.rulename if (sourcekind == "as" or sourcekind == "mrc") then -- no common flags for as/mrc files for _, sourcefile in ipairs(sourcebatch.sourcefiles) do sourceflags[sourcefile] = targetinfo.sourceflags[sourcefile] end - elseif (sourcekind == "cc" or sourcekind == "cxx") then + elseif rulename == "c.build" or rulename == "c++.build" then -- sourcekind maybe bind multiple rules, e.g. c++modules for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local flags = targetinfo.sourceflags[sourcefile] local otherflags = {} @@ -1313,7 +1315,8 @@ function _make_source_files(vcxprojfile, vsinfo, target) for _, targetinfo in ipairs(target.info) do for _, sourcebatch in pairs(targetinfo.sourcebatches) do local sourcekind = sourcebatch.sourcekind - if (sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "as" or sourcekind == "mrc" or sourcekind == "cu") then + local rulename = sourcebatch.rulename + if (rulename == "c.build" or rulename == "c++.build" or sourcekind == "as" or sourcekind == "mrc" or sourcekind == "cu") then local objectfiles = sourcebatch.objectfiles for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = objectfiles[idx] -- cgit v1.3.1 From e35342220927bc044f4e07c00713d904a3618b08 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 22:41:55 +0800 Subject: enable full parallel build for modules --- xmake/rules/c++/modules/xmake.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3ef960d7a..feb53785d 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -27,14 +27,8 @@ rule("c++.build.modules") on_config(function (target) import("modules_support.common") - -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 if common.contains_modules(target) then - -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, - -- even if some sub-targets do not contain C++ modules. - -- - -- maybe we will have a more fine-grained configuration strategy to disable it in the future. - target:set("policy", "build.across_targets_in_parallel", false) -- get modules support local modules_support = common.modules_support(target) -- cgit v1.3.1 From 61c9bf5fe8ec9f2607c0cbd15983c3dd2054563e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 22:48:20 +0800 Subject: revert parallel build --- xmake/rules/c++/modules/xmake.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index feb53785d..3ef960d7a 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -27,8 +27,14 @@ rule("c++.build.modules") on_config(function (target) import("modules_support.common") + -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 if common.contains_modules(target) then + -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, + -- even if some sub-targets do not contain C++ modules. + -- + -- maybe we will have a more fine-grained configuration strategy to disable it in the future. + target:set("policy", "build.across_targets_in_parallel", false) -- get modules support local modules_support = common.modules_support(target) -- cgit v1.3.1 From 4aeb3af55ff8ab7c1954fac444b24284f306604a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 22:52:48 +0800 Subject: ignore color codes --- xmake/plugins/project/cmake/cmakelists.lua | 3 ++- xmake/plugins/project/vstudio/impl/vs201x.lua | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 130c1ad38..5154956e6 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.base.colors") import("core.project.project") import("core.project.config") import("core.tool.compiler") @@ -828,7 +829,7 @@ function _get_command_string(cmd, outputdir) elseif kind == "mkdir" then return string.format("${CMAKE_COMMAND} -E make_directory %s", _get_unix_path_relative_to_cmake(cmd.dir, outputdir)) elseif kind == "show" then - return string.format("echo %s", cmd.showtext) + return string.format("echo %s", colors.ignore(cmd.showtext)) end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index ce843d725..6fcb5a3a8 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -20,6 +20,7 @@ -- imports import("core.base.option") +import("core.base.colors") import("core.project.rule") import("core.project.config") import("core.project.project") @@ -109,7 +110,7 @@ function _get_command_string(cmd, vcxprojdir) local dir = _translate_path(cmd.dir, vcxprojdir) return string.format("if not exist \"%s\" mkdir \"%s\"", dir, dir) elseif kind == "show" then - return string.format("echo %s", cmd.showtext) + return string.format("echo %s", colors.ignore(cmd.showtext)) end end -- cgit v1.3.1 From d9f82e1bba29adc8b11dc1f7b3887717f03137d6 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Aug 2022 22:53:13 +0800 Subject: clear cxxmodules cache for vs --- xmake/plugins/project/vstudio/impl/vs201x.lua | 1 + xmake/plugins/project/vsxmake/getinfo.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 6fcb5a3a8..5d0e730d9 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -544,6 +544,7 @@ function make(outputdir, vsinfo) localcache.clear("option") localcache.clear("package") localcache.clear("toolchain") + localcache.clear("cxxmodules") -- check platform platform.load(config.plat(), arch):check() diff --git a/xmake/plugins/project/vsxmake/getinfo.lua b/xmake/plugins/project/vsxmake/getinfo.lua index e45947482..49bbfe745 100644 --- a/xmake/plugins/project/vsxmake/getinfo.lua +++ b/xmake/plugins/project/vsxmake/getinfo.lua @@ -468,6 +468,7 @@ function main(outputdir, vsinfo) localcache.clear("option") localcache.clear("package") localcache.clear("toolchain") + localcache.clear("cxxmodules") -- check platform platform.load(config.plat(), arch):check() -- cgit v1.3.1