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/modules_support/common.lua | 423 +++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 xmake/rules/c++/modules/modules_support/common.lua (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 -- 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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 (limited to 'xmake/rules/c++/modules/modules_support/common.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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(+) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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 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(-) (limited to 'xmake/rules/c++/modules/modules_support/common.lua') 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