From d52291f3389b2bf3f4b90e24c4670f41605c3cc8 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 23 Jan 2024 18:23:27 +0100 Subject: refactor module common infrastructure --- .../rules/c++/modules/modules_support/builder.lua | 400 +++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 xmake/rules/c++/modules/modules_support/builder.lua (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua new file mode 100644 index 000000000..481415661 --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -0,0 +1,400 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Arthapz +-- @file common.lua +-- + +-- imports +import("core.base.json") +import("core.base.option") +import("private.async.buildjobs") +import("core.tool.compiler") +import("core.project.config") +import("core.project.depend") +import("utils.progress") +import("compiler_support") +import("dependency_scanner") + +-- build target modules +function _build_modules(target, sourcebatch, modules, opt) + local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + + -- build modules + for _, objectfile in ipairs(objectfiles) do + local module = modules[objectfile] + if not module then + goto CONTINUE + end + + local name, provide, cppfile = compiler_support.get_provided_module(module) + cppfile = cppfile or module.cppfile + + local fileconfig = target:fileconfig(cppfile) + local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) + local build = _should_build(target, cppfile, bmifile, objectfile, module.requires) + + -- add objectfile if module is not from external dep + if not (fileconfig and fileconfig.external) then + target:add("objectfiles", objectfile) + end + + -- needed to detect rebuild of dependencies + if provide then + compiler_support.memcache():set2(target:name(), name, build) + end + + local deps = {} + for _, dep in ipairs(table.keys(module.requires or {})) do + table.insert(deps, opt.batchjobs and target:name() .. dep or dep) + end + + opt.build_module(deps, build, module, name, provide, objectfile, cppfile, fileconfig) + + ::CONTINUE:: + end +end + +-- build target headerunits +function _build_headerunits(target, headerunits, opt) + + local outputdir = compiler_support.headerunits_cachedir(target, {mkdir = true}) + if opt.stl_headerunit then + outputdir = path.join(outputdir, "stl") + end + + for _, headerunit in ipairs(headerunits) do + local outputdir = outputdir + if opt.stl_headerunit and headerunit.name:startswith("experimental/") then + outputdir = path.join(outputdir, "experimental") + end + local bmifile = path.join(outputdir, path.filename(headerunit.name) .. compiler_support.get_bmi_extension(target)) + local key = path.normalize(headerunit.path) + local build = _should_build(target, headerunit.path, bmifile, nil, nil, {key = key, headerunit = true}) + + compiler_support.memcache():set2(target:name(), key, build) + + opt.build_headerunit(headerunit, key, bmifile, outputdir, build) + end +end + +-- should we build this module or headerunit ? +function _should_build(target, sourcefile, bmifile, objectfile, requires, opt) + + -- force rebuild a module if any of its module dependency is rebuilt + if requires then + for required, _ in pairs(requires) do + local m = get_from_target_mapper(target, required) + if m then + local rebuild = compiler_support.memcache():get2(target:name(), m.key) + if rebuild then + return true + end + end + end + end + + -- or rebuild it if the file changed for headerunit and namedmodules + if compiler_support.has_module_extension(sourcefile) or (opt and opt.headerunit) then + local dryrun = option.get("dry-run") + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) + + local dependfile = target:dependfile(bmifile or objectfile) + local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) + + -- need build this object? + local depvalues = {compinst:program(), compflags} + local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 + + if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then + return true + end + end + + return false +end + +-- generate meta module informations for package / other buildsystems import +-- +-- e.g +-- { +-- "defines": ["FOO=BAR"] +-- "imports": ["std", "bar"] +-- "name": "foo" +-- "file": "foo.cppm" +-- } +function _generate_meta_module_info(target, name, sourcefile, requires) + + local modulehash = compiler_support.get_modulehash(target, sourcefile) + local module_metadata = {name = name, file = path.join(modulehash, path.filename(sourcefile))} + + -- add definitions + module_metadata.defines = _builder(target).get_module_required_defines(target, sourcefile) + + -- add imports + if requires then + for _name, _ in pairs(requires) do + module_metadata.imports = module_metadata.imports or {} + table.append(module_metadata.imports, _name) + end + end + + return module_metadata +end + +function _target_module_map_cachekey(target) + local mode = config.mode() + return target:name() .. "module_mapper" .. (mode or "") +end + +function _is_duplicated_headerunit(target, headerunit) + local mapper = get_target_module_mapper(target) + local key = hash.md5(path.normalize(headerunit.path)) + + -- for _, mapped in pairs(mapper) do + -- print("CHECK", mapped.key, key) + -- if mapped.key == key then + -- return true + -- end + -- end + + return false +end + +-- add populate job +function _init_build_for(target, batch, modules, opt) + + if opt.batchjobs then + local job_name = get_modulemap_populate_jobname(target) + return { modulemap_populatejob_name = { + name = job_name, + job = batch:addjob(job_name, function(index, total) + progress.show((index * 100) / total, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + _builder(target).populate_module_map(target, modules) + end)}} + else + batch:show_progress(opt.progress, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + _builder(target).populate_module_map(target, modules) + end +end + +function _builder(target) + + local cachekey = tostring(target) + local builder = compiler_support.memcache():get2("builder", cachekey) + if builder == nil then + if target:has_tool("cxx", "clang", "clangxx") then + builder = import("clang.builder", {anonymous = true}) + elseif target:has_tool("cxx", "gcc", "gxx") then + builder = import("gcc.builder", {anonymous = true}) + elseif target:has_tool("cxx", "cl") then + builder = import("msvc.builder", {anonymous = true}) + else + local _, toolname = target:tool("cxx") + raise("compiler(%s): does not support c++ module!", toolname) + end + compiler_support.memcache():set2("builder", cachekey, builder) + end + return builder +end + +function get_modulemap_populate_jobname(target) + return target:name() .. "_module_map_populate" +end + +-- build batchjobs for modules +function build_batchjobs_for_modules(modules, batchjobs, rootjob) + return buildjobs(modules, batchjobs, rootjob) +end + +-- build modules for batchjobs +function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + + opt.rootjob = batchjobs:group_leave() or opt.rootjob + batchjobs:group_enter(target:name() .. "/build_modules", {rootjob = opt.rootjob}) + + local modulesjobs = {} + + _build_modules(target, sourcebatch, modules, table.join(opt, { + build_module = function(deps, build, module, name, provide, objectfile, cppfile, fileconfig) + local job_name = name and target:name() .. name or cppfile + + modulesjobs[job_name] = _builder(target).make_module_build_job(target, batchjobs, job_name, deps, {build = build, module = module, objectfile = objectfile, cppfile = cppfile}) + + if provide and fileconfig and fileconfig.public then + batchjobs:addjob(name .. "_metafile", function(index, total) + local metafilepath = compiler_support.get_metafile(target, cppfile) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name) + local metadata = _generate_meta_module_info(target, name, cppfile, module.requires) + json.savefile(metafilepath, metadata) + end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()}) + end, {rootjob = opt.rootjob}) + end + end + })) + + local tailjob = _init_build_for(target, batchjobs, modules, table.join({type = "module"}, opt)) + table.join2(modulesjobs, tailjob) + + -- build batchjobs for modules + build_batchjobs_for_modules(modulesjobs, batchjobs, opt.rootjob) +end + +-- build modules for batchcmds +function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + + local depmtime = 0 + opt.progress = opt.progress or 0 + _init_build_for(target, batchcmds, modules, table.join({type = "module"}, opt)) + + -- build modules + _build_modules(target, sourcebatch, modules, table.join(opt, { + build_module = function(_, build, module, name, provide, objectfile, cppfile, fileconfig) + depmtime = math.max(depmtime, _builder(target).make_module_build_cmds(target, batchcmds, {build = build, module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) + + if provide and fileconfig and fileconfig.public then + local metafilepath = compiler_support.get_metafile(target, cppfile) + depend.on_changed(function() + progress.show(opt.progress, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name) + local metadata = _generate_meta_module_info(target, name, cppfile, module.requires) + json.savefile(metafilepath, metadata) + end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()}) + end + end + })) + + batchcmds:set_depmtime(depmtime) +end + +-- generate headerunits for batchjobs +function build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + + local user_headerunits, stl_headerunits = dependency_scanner.get_headerunits(target, sourcebatch, modules) + if not user_headerunits and not stl_headerunits then + return + end + -- we need new group(headerunits) + -- e.g. group(build_modules) -> group(headerunits) + opt.rootjob = batchjobs:group_leave() or opt.rootjob + batchjobs:group_enter(target:name() .. "/build_headerunits", {rootjob = opt.rootjob}) + + local build_headerunits = function(headerunits) + local modulesjobs = {} + _build_headerunits(target, headerunits, table.join(opt, { + build_headerunit = function(headerunit, key, bmifile, outputdir, build) + local job_name = target:name() .. key + local job = _builder(target).make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, table.join(opt, {build = build})) + if job then + modulesjobs[job_name] = job + end + end + })) + build_batchjobs_for_modules(modulesjobs, batchjobs, opt.rootjob) + end + + -- build stl header units first as other headerunits may need them + if stl_headerunits then + opt.stl_headerunit = true + build_headerunits(stl_headerunits) + end + if user_headerunits then + opt.stl_headerunit = false + build_headerunits(user_headerunits) + end +end + +-- generate headerunits for batchcmds +function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + + local user_headerunits, stl_headerunits = dependency_scanner.get_headerunits(target, sourcebatch, modules) + if not user_headerunits and not stl_headerunits then + return + end + + local build_headerunits = function(headerunits) + local depmtime = 0 + _build_headerunits(target, headerunits, table.join(opt, { + build_headerunit = function(headerunit, _, bmifile, outputdir, build) + depmtime = math.max(depmtime, _builder(target).make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, table.join({build = build}, opt))) + end + })) + batchcmds:set_depmtime(depmtime) + end + + -- build stl header units first as other headerunits may need them + if stl_headerunits then + opt.stl_headerunit = true + build_headerunits(stl_headerunits) + end + if user_headerunits then + opt.stl_headerunit = false + build_headerunits(user_headerunits) + end +end + +-- append headerunits objectfiles to link +function append_dependency_objectfiles(target) + + local cachekey = target:name() .. "dependency_objectfiles" + local cache = compiler_support.localcache():get(cachekey) + if cache then + if target:is_binary() then + target:add("ldflags", cache, {force = true, expand = false}) + elseif target:is_static() then + target:add("arflags", cache, {force = true, expand = false}) + elseif target:is_shared() then + target:add("shflags", cache, {force = true, expand = false}) + end + end +end + +-- get or create a target module mapper +function get_target_module_mapper(target) + + opt = opt or {} + local memcache = compiler_support.memcache() + local mapper = memcache:get2(target:name(), "module_mapper") + if not mapper then + mapper = {} + memcache:set2(target:name(), "module_mapper", mapper) + end + + return mapper +end + +-- get a module or headerunit from target mapper +function get_from_target_mapper(target, name) + local mapper = get_target_module_mapper(target) + if mapper[name] then + return mapper[name] + end +end + +-- add a module to target mapper +function add_module_to_target_mapper(target, name, sourcefile, bmifile, opt) + local mapper = get_target_module_mapper(target) + mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} +end + +-- add a headerunit to target mapper +function add_headerunit_to_target_mapper(target, headerunit, bmifile) + local mapper = get_target_module_mapper(target) + mapper[headerunit.name] = {name = headerunit.name, key = path.normalize(headerunit.path), headerunit = headerunit, bmi = bmifile} + return _is_duplicated_headerunit(target, headerunit) +end + -- cgit v1.3.1 From d50a83fbfcd59db2a8a5fc0f8fe14770f9a0d16b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 29 Jan 2024 12:18:01 +0100 Subject: apply PR suggestions --- xmake/rules/c++/modules/modules_support/builder.lua | 13 +++++++++++-- .../c++/modules/modules_support/clang/compiler_support.lua | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 481415661..4592e547d 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -33,6 +33,8 @@ import("dependency_scanner") function _build_modules(target, sourcebatch, modules, opt) local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + compiler_support.memcache():set2(target:name(), "need_to_repopulate", false) + -- build modules for _, objectfile in ipairs(objectfiles) do local module = modules[objectfile] @@ -62,6 +64,9 @@ function _build_modules(target, sourcebatch, modules, opt) table.insert(deps, opt.batchjobs and target:name() .. dep or dep) end + if build then + compiler_support.memcache():set2(target:name(), "need_to_repopulate", true) + end opt.build_module(deps, build, module, name, provide, objectfile, cppfile, fileconfig) ::CONTINUE:: @@ -183,11 +188,15 @@ function _init_build_for(target, batch, modules, opt) return { modulemap_populatejob_name = { name = job_name, job = batch:addjob(job_name, function(index, total) - progress.show((index * 100) / total, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + if compiler_support.memcache():get2(target:name(), "need_to_repopulate") then + progress.show((index * 100) / total, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + end _builder(target).populate_module_map(target, modules) end)}} else - batch:show_progress(opt.progress, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + if compiler_support.memcache():get2(target:name(), "need_to_repopulate") then + batch:show_progress(opt.progress, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) + end _builder(target).populate_module_map(target, modules) end end diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 95578acee..6e4b36645 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -60,11 +60,11 @@ function get_cpplibrary_name(target) local runtime = target:runtimes() if not runtime then - if is_plat("windows") then + if target:is_plat("windows") then runtime = "msstl" - elseif is_plat("linux") or is_plat("android") then + elseif target:is_plat("linux") or target:is_plat("android") then runtime = "stdc++_shared" - elseif is_plat("macosx") or is_plat("iphoneos") or is_plat("watchos") then + elseif target:is_plat("macosx") or target:is_plat("iphoneos") or target:is_plat("watchos") then runtime = "c++_shared" end end -- cgit v1.3.1 From 952b8132bc699310d9f2750536079e81603ffe56 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 29 Jan 2024 17:43:09 +0100 Subject: populate module map before generating batchjobs --- .../rules/c++/modules/modules_support/builder.lua | 34 +--------------------- .../c++/modules/modules_support/clang/builder.lua | 3 +- .../c++/modules/modules_support/gcc/builder.lua | 3 +- .../c++/modules/modules_support/msvc/builder.lua | 3 +- 4 files changed, 4 insertions(+), 39 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 4592e547d..099c0993e 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -33,7 +33,7 @@ import("dependency_scanner") function _build_modules(target, sourcebatch, modules, opt) local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) - compiler_support.memcache():set2(target:name(), "need_to_repopulate", false) + _builder(target).populate_module_map(target, modules) -- build modules for _, objectfile in ipairs(objectfiles) do @@ -64,9 +64,6 @@ function _build_modules(target, sourcebatch, modules, opt) table.insert(deps, opt.batchjobs and target:name() .. dep or dep) end - if build then - compiler_support.memcache():set2(target:name(), "need_to_repopulate", true) - end opt.build_module(deps, build, module, name, provide, objectfile, cppfile, fileconfig) ::CONTINUE:: @@ -180,27 +177,6 @@ function _is_duplicated_headerunit(target, headerunit) return false end --- add populate job -function _init_build_for(target, batch, modules, opt) - - if opt.batchjobs then - local job_name = get_modulemap_populate_jobname(target) - return { modulemap_populatejob_name = { - name = job_name, - job = batch:addjob(job_name, function(index, total) - if compiler_support.memcache():get2(target:name(), "need_to_repopulate") then - progress.show((index * 100) / total, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) - end - _builder(target).populate_module_map(target, modules) - end)}} - else - if compiler_support.memcache():get2(target:name(), "need_to_repopulate") then - batch:show_progress(opt.progress, "${color.build.target}<%s> populating.%s.map", target:name(), opt.type) - end - _builder(target).populate_module_map(target, modules) - end -end - function _builder(target) local cachekey = tostring(target) @@ -221,10 +197,6 @@ function _builder(target) return builder end -function get_modulemap_populate_jobname(target) - return target:name() .. "_module_map_populate" -end - -- build batchjobs for modules function build_batchjobs_for_modules(modules, batchjobs, rootjob) return buildjobs(modules, batchjobs, rootjob) @@ -257,9 +229,6 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op end })) - local tailjob = _init_build_for(target, batchjobs, modules, table.join({type = "module"}, opt)) - table.join2(modulesjobs, tailjob) - -- build batchjobs for modules build_batchjobs_for_modules(modulesjobs, batchjobs, opt.rootjob) end @@ -269,7 +238,6 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op local depmtime = 0 opt.progress = opt.progress or 0 - _init_build_for(target, batchcmds, modules, table.join({type = "module"}, opt)) -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 0e51bd93e..947a03bfc 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -201,11 +201,10 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) local dryrun = option.get("dry-run") - local populate_job_name = get_modulemap_populate_jobname(target) return { name = job_name, - deps = table.join({populate_job_name}, deps), + deps = deps, sourcefile = cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 6e76a7646..5776b7010 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -235,11 +235,10 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) local module_mapperflag = compiler_support.get_modulemapperflag(target) - local populate_job_name = get_modulemap_populate_jobname(target) return { name = job_name, - deps = table.join({populate_job_name}, deps), + deps = deps, sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 0f4f9b735..3b295ca6b 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -197,11 +197,10 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) local dryrun = option.get("dry-run") - local populate_job_name = get_modulemap_populate_jobname(target) return { name = job_name, - deps = table.join({populate_job_name}, deps), + deps = deps, sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) -- cgit v1.3.1 From cc88697bbfe2925c6e290f400974da8c4c2f0e2c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 12:20:23 +0100 Subject: remove dead code --- xmake/rules/c++/modules/modules_support/builder.lua | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 099c0993e..e0885a2aa 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -324,22 +324,6 @@ function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules end end --- append headerunits objectfiles to link -function append_dependency_objectfiles(target) - - local cachekey = target:name() .. "dependency_objectfiles" - local cache = compiler_support.localcache():get(cachekey) - if cache then - if target:is_binary() then - target:add("ldflags", cache, {force = true, expand = false}) - elseif target:is_static() then - target:add("arflags", cache, {force = true, expand = false}) - elseif target:is_shared() then - target:add("shflags", cache, {force = true, expand = false}) - end - end -end - -- get or create a target module mapper function get_target_module_mapper(target) -- cgit v1.3.1 From 95996d7b59b420f9bc6b9f8e817e48d6be183acc Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 12:29:37 +0100 Subject: improve _should_build --- .../rules/c++/modules/modules_support/builder.lua | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index e0885a2aa..b17bb73b3 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -47,7 +47,7 @@ function _build_modules(target, sourcebatch, modules, opt) local fileconfig = target:fileconfig(cppfile) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) - local build = _should_build(target, cppfile, bmifile, objectfile, module.requires) + local build = _should_build(target, cppfile, bmifile, {objectfile = objectfile, requires = module.requires}) -- add objectfile if module is not from external dep if not (fileconfig and fileconfig.external) then @@ -55,8 +55,8 @@ function _build_modules(target, sourcebatch, modules, opt) end -- needed to detect rebuild of dependencies - if provide then - compiler_support.memcache():set2(target:name(), name, build) + if provide and build then + _mark_build(target, name) end local deps = {} @@ -85,23 +85,26 @@ function _build_headerunits(target, headerunits, opt) end local bmifile = path.join(outputdir, path.filename(headerunit.name) .. compiler_support.get_bmi_extension(target)) local key = path.normalize(headerunit.path) - local build = _should_build(target, headerunit.path, bmifile, nil, nil, {key = key, headerunit = true}) + local build = _should_build(target, headerunit.path, bmifile, {key = key, headerunit = true}) - compiler_support.memcache():set2(target:name(), key, build) + if build then + _mark_build(target, key) + end opt.build_headerunit(headerunit, key, bmifile, outputdir, build) end end -- should we build this module or headerunit ? -function _should_build(target, sourcefile, bmifile, objectfile, requires, opt) +function _should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt + local requires = opt.requires if requires then for required, _ in pairs(requires) do local m = get_from_target_mapper(target, required) if m then - local rebuild = compiler_support.memcache():get2(target:name(), m.key) + local rebuild = compiler_support.memcache():get2("should_build_in" .. target:name(), m.key) if rebuild then return true end @@ -110,6 +113,7 @@ function _should_build(target, sourcefile, bmifile, objectfile, requires, opt) end -- or rebuild it if the file changed for headerunit and namedmodules + local objectfile = opt.objectfile if compiler_support.has_module_extension(sourcefile) or (opt and opt.headerunit) then local dryrun = option.get("dry-run") local compinst = compiler.load("cxx", {target = target}) @@ -197,6 +201,10 @@ function _builder(target) return builder end +function _mark_build(target, name) + compiler_support.memcache():set2("should_build_in" .. target:name(), name, true) +end + -- build batchjobs for modules function build_batchjobs_for_modules(modules, batchjobs, rootjob) return buildjobs(modules, batchjobs, rootjob) -- cgit v1.3.1 From f3ec9cc0f7cf6d0b48dce8a69c5f6103b9dd6df3 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 13:01:40 +0100 Subject: implement missing headerunit aliasing --- .../rules/c++/modules/modules_support/builder.lua | 27 ++++++----- .../c++/modules/modules_support/clang/builder.lua | 56 +++++++++++++--------- .../c++/modules/modules_support/gcc/builder.lua | 19 +++++++- .../c++/modules/modules_support/msvc/builder.lua | 18 ++++++- 4 files changed, 80 insertions(+), 40 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index b17bb73b3..5c2ec113f 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -167,18 +167,13 @@ function _target_module_map_cachekey(target) return target:name() .. "module_mapper" .. (mode or "") end -function _is_duplicated_headerunit(target, headerunit) +function _is_duplicated_headerunit(target, key) local mapper = get_target_module_mapper(target) - local key = hash.md5(path.normalize(headerunit.path)) - - -- for _, mapped in pairs(mapper) do - -- print("CHECK", mapped.key, key) - -- if mapped.key == key then - -- return true - -- end - -- end - - return false + for _, mapped in pairs(mapper) do + if mapped.key == key then + return mapped + end + end end function _builder(target) @@ -363,7 +358,13 @@ end -- add a headerunit to target mapper function add_headerunit_to_target_mapper(target, headerunit, bmifile) local mapper = get_target_module_mapper(target) - mapper[headerunit.name] = {name = headerunit.name, key = path.normalize(headerunit.path), headerunit = headerunit, bmi = bmifile} - return _is_duplicated_headerunit(target, headerunit) + local key = hash.uuid(path.normalize(headerunit.path)) + local deduplicated = _is_duplicated_headerunit(target, key) + if deduplicated then + mapper[headerunit.name] = {name = headerunit.name, key = key, aliasof = deduplicated.name} + else + mapper[headerunit.name] = {name = headerunit.name, key = key, headerunit = headerunit, bmi = bmifile} + end + return deduplicated and true or false end diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 1b414215f..6a2893ea9 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -134,7 +134,15 @@ function _get_requiresflags(target, module, opt) assert(dep_module, "module dependency %s required for %s not found", required, name) - local bmifile = dep_module.bmi + local bmifile + -- aliased headerunit + if dep_module.aliasof then + local aliased = get_from_target_mapper(target, dep_module.aliasof) + bmifile = aliased.bmi + -- named module or headerunit + else + bmifile = dep_module.bmi + end local mapflag = (dep_module.opt and dep_module.opt.namedmodule) and format("%s%s=%s", modulefileflag, required, bmifile) or modulefileflag .. bmifile table.insert(requiresflags, mapflag) @@ -286,32 +294,34 @@ end -- build headerunit file for batchjobs function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) - add_headerunit_to_target_mapper(target, headerunit, bmifile) - return { - name = job_name, - sourcefile = headerunit.path, - job = batchjobs:newjob(job_name, function(index, total) - if not os.isdir(outputdir) then - os.mkdir(outputdir) - end + local already_exists = add_headerunit_to_target_mapper(target, headerunit, bmifile) + if not already_exists then + return { + name = job_name, + sourcefile = headerunit.path, + job = batchjobs:newjob(job_name, function(index, total) + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = headerunit.path, target = target}) + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = headerunit.path, target = target}) - local dependfile = target:dependfile(bmifile) - local dependinfo = depend.load(dependfile) or {} - dependinfo.files = {} - local depvalues = {compinst:program(), compflags} + local dependfile = target:dependfile(bmifile) + local dependinfo = depend.load(dependfile) or {} + dependinfo.files = {} + local depvalues = {compinst:program(), compflags} - if opt.build then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.headerunit.$(mode) %s", target:name(), headerunit.name) - _compile(target, _make_headerunitflags(target, headerunit, bmifile), headerunit.path) - end + if opt.build then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.headerunit.$(mode) %s", target:name(), headerunit.name) + _compile(target, _make_headerunitflags(target, headerunit, bmifile), headerunit.path) + end - table.insert(dependinfo.files, headerunit.path) - dependinfo.values = depvalues - depend.save(dependinfo, dependfile) - end)} + table.insert(dependinfo.files, headerunit.path) + dependinfo.values = depvalues + depend.save(dependinfo, dependfile) + end)} + end end -- build headerunit file for batchcmds diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 13755660d..19f5e813b 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -151,12 +151,27 @@ function _get_maplines(target, module) assert(dep_module, "module dependency %s required for %s not found", required, name) - local mapline = (dep_module.headerunit and dep_module.headerunit.path:replace("\\", "/") or required) .. " " .. dep_module.bmi:replace("\\", "/") + local bmifile + local mapline + -- aliased headerunit + if dep_module.aliasof then + local aliased = get_from_target_mapper(target, dep_module.aliasof) + bmifile = aliased.bmi + mapline = dep_module.headerunit.path:replace("\\", "/") .. " " bmifile:replace("\\", "/") + -- headerunit + elseif dep_module.headerunit then + bmifile = dep_module.bmi + mapline = dep_module.headerunit.path:replace("\\", "/") .. " " bmifile:replace("\\", "/") + -- named module + else + bmifile = dep_module.bmi + mapline = required .. " " .. bmifile:replace("\\", "/") + end table.insert(maplines, mapline) -- append deps if dep_module.opt and dep_module.opt.deps then - local deps = _get_maplines(dep_target, { name = dep_module.name, bmi = dep_module.bmifile, requires = dep_module.opt.deps }) + local deps = _get_maplines(dep_target, { name = dep_module.name, bmi = bmifile, requires = dep_module.opt.deps }) table.join2(maplines, deps) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 8a77a7612..9b7bd330e 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -122,8 +122,22 @@ function _get_requiresflags(target, module, opt) assert(dep_module, "module dependency %s required for %s not found <%s>", required, name, target:name()) - local bmifile = dep_module.bmi - local mapflag = {dep_module.headerunit and headerunitflag .. dep_module.headerunit.type or referenceflag, required .. "=" .. bmifile} + local mapflag + local bmifile + -- aliased headerunit + if dep_module.aliasof then + local aliased = get_from_target_mapper(target, dep_module.aliasof) + bmifile = aliased.bmi + mapflag = {headerunitflag .. aliased.headerunit.type, required .. "=" .. bmifile} + -- headerunit + elseif dep_module.headerunit then + bmifile = dep_module.bmi + mapflag = {headerunitflag .. dep_module.headerunit.type, required .. "=" .. bmifile} + -- named module + else + bmifile = dep_module.bmi + mapflag = {referenceflag, required .. "=" .. bmifile} + end table.insert(deps_flags, mapflag) -- append deps -- cgit v1.3.1 From 89f151ab335ad2aa1e5d1cc900f1e3837caa6437 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 13:02:11 +0100 Subject: add a test for aliased headerunits --- .../c++/modules/aliased_headerunit/src/foo/hello.mpp | 12 ++++++++++++ tests/projects/c++/modules/aliased_headerunit/src/header.hpp | 5 +++++ tests/projects/c++/modules/aliased_headerunit/src/main.cpp | 7 +++++++ tests/projects/c++/modules/aliased_headerunit/test.lua | 1 + tests/projects/c++/modules/aliased_headerunit/xmake.lua | 8 ++++++++ xmake/rules/c++/modules/modules_support/builder.lua | 2 +- xmake/rules/c++/modules/modules_support/clang/builder.lua | 5 +---- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 12 +++++------- xmake/rules/c++/modules/modules_support/msvc/builder.lua | 4 +--- 9 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 tests/projects/c++/modules/aliased_headerunit/src/foo/hello.mpp create mode 100644 tests/projects/c++/modules/aliased_headerunit/src/header.hpp create mode 100644 tests/projects/c++/modules/aliased_headerunit/src/main.cpp create mode 100644 tests/projects/c++/modules/aliased_headerunit/test.lua create mode 100644 tests/projects/c++/modules/aliased_headerunit/xmake.lua (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/tests/projects/c++/modules/aliased_headerunit/src/foo/hello.mpp b/tests/projects/c++/modules/aliased_headerunit/src/foo/hello.mpp new file mode 100644 index 000000000..0a8de6291 --- /dev/null +++ b/tests/projects/c++/modules/aliased_headerunit/src/foo/hello.mpp @@ -0,0 +1,12 @@ +module; +#include + +export module hello; + +import "../header.hpp"; + +export namespace hello { + void say(const char *arg) { + printf("%s: %s\n", FOO, arg); + } +} diff --git a/tests/projects/c++/modules/aliased_headerunit/src/header.hpp b/tests/projects/c++/modules/aliased_headerunit/src/header.hpp new file mode 100644 index 000000000..ab02a6792 --- /dev/null +++ b/tests/projects/c++/modules/aliased_headerunit/src/header.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace hello { + inline constexpr auto FOO = "Hello"; +} diff --git a/tests/projects/c++/modules/aliased_headerunit/src/main.cpp b/tests/projects/c++/modules/aliased_headerunit/src/main.cpp new file mode 100644 index 000000000..ad786367e --- /dev/null +++ b/tests/projects/c++/modules/aliased_headerunit/src/main.cpp @@ -0,0 +1,7 @@ +import hello; +import "header.hpp"; + +int main() { + hello::say(hello::FOO); + return 0; +} diff --git a/tests/projects/c++/modules/aliased_headerunit/test.lua b/tests/projects/c++/modules/aliased_headerunit/test.lua new file mode 100644 index 000000000..c18e5a1d0 --- /dev/null +++ b/tests/projects/c++/modules/aliased_headerunit/test.lua @@ -0,0 +1 @@ +inherit(".test_headerunits") diff --git a/tests/projects/c++/modules/aliased_headerunit/xmake.lua b/tests/projects/c++/modules/aliased_headerunit/xmake.lua new file mode 100644 index 000000000..5b4827d09 --- /dev/null +++ b/tests/projects/c++/modules/aliased_headerunit/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +set_languages("c++20") + +-- header.hpp should be built only one time +target("aliased_headerunit") + set_kind("binary") + add_headerfiles("src/*.hpp") + add_files("src/*.cpp", "src/foo/*.mpp") diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 5c2ec113f..db986b4ff 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -361,7 +361,7 @@ function add_headerunit_to_target_mapper(target, headerunit, bmifile) local key = hash.uuid(path.normalize(headerunit.path)) local deduplicated = _is_duplicated_headerunit(target, key) if deduplicated then - mapper[headerunit.name] = {name = headerunit.name, key = key, aliasof = deduplicated.name} + mapper[headerunit.name] = {name = headerunit.name, key = key, aliasof = deduplicated.name, headerunit = headerunit} else mapper[headerunit.name] = {name = headerunit.name, key = key, headerunit = headerunit, bmi = bmifile} end diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 6a2893ea9..2c17318d4 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -134,14 +134,11 @@ function _get_requiresflags(target, module, opt) assert(dep_module, "module dependency %s required for %s not found", required, name) - local bmifile + local bmifile = dep_module.bmi -- aliased headerunit if dep_module.aliasof then local aliased = get_from_target_mapper(target, dep_module.aliasof) bmifile = aliased.bmi - -- named module or headerunit - else - bmifile = dep_module.bmi end local mapflag = (dep_module.opt and dep_module.opt.namedmodule) and format("%s%s=%s", modulefileflag, required, bmifile) or modulefileflag .. bmifile table.insert(requiresflags, mapflag) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 19f5e813b..95be560d9 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -151,20 +151,18 @@ function _get_maplines(target, module) assert(dep_module, "module dependency %s required for %s not found", required, name) - local bmifile + local bmifile = dep_module.bmi local mapline -- aliased headerunit if dep_module.aliasof then local aliased = get_from_target_mapper(target, dep_module.aliasof) bmifile = aliased.bmi - mapline = dep_module.headerunit.path:replace("\\", "/") .. " " bmifile:replace("\\", "/") + mapline = dep_module.headerunit.path:replace("\\", "/") .. " " .. bmifile:replace("\\", "/") -- headerunit elseif dep_module.headerunit then - bmifile = dep_module.bmi - mapline = dep_module.headerunit.path:replace("\\", "/") .. " " bmifile:replace("\\", "/") + mapline = dep_module.headerunit.path:replace("\\", "/") .. " " .. bmifile:replace("\\", "/") -- named module else - bmifile = dep_module.bmi mapline = required .. " " .. bmifile:replace("\\", "/") end table.insert(maplines, mapline) @@ -214,7 +212,7 @@ function populate_module_map(target, modules) for _, module in pairs(modules) do local name, provide = compiler_support.get_provided_module(module) if provide then - add_module_to_target_mapper(target, name, provide.sourcefile, path.absolute(compiler_support.get_bmi_path(provide.bmi), projectdir)) + add_module_to_target_mapper(target, name, provide.sourcefile, compiler_support.get_bmi_path(provide.bmi)) end end @@ -223,7 +221,7 @@ function populate_module_map(target, modules) local name, provide = compiler_support.get_provided_module(module) if provide then local bmifile = compiler_support.get_bmi_path(provide.bmi) - add_module_to_target_mapper(target, name, provide.sourcefile, path.absolute(bmifile, projectdir), {deps = module.requires}) + add_module_to_target_mapper(target, name, provide.sourcefile, bmifile, {deps = module.requires}) end end end diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 9b7bd330e..00326143e 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -123,7 +123,7 @@ function _get_requiresflags(target, module, opt) assert(dep_module, "module dependency %s required for %s not found <%s>", required, name, target:name()) local mapflag - local bmifile + local bmifile = dep_module.bmi -- aliased headerunit if dep_module.aliasof then local aliased = get_from_target_mapper(target, dep_module.aliasof) @@ -131,11 +131,9 @@ function _get_requiresflags(target, module, opt) mapflag = {headerunitflag .. aliased.headerunit.type, required .. "=" .. bmifile} -- headerunit elseif dep_module.headerunit then - bmifile = dep_module.bmi mapflag = {headerunitflag .. dep_module.headerunit.type, required .. "=" .. bmifile} -- named module else - bmifile = dep_module.bmi mapflag = {referenceflag, required .. "=" .. bmifile} end table.insert(deps_flags, mapflag) -- cgit v1.3.1 From 15f2678a507c933f1f1456a496cb31e0373699f2 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 14:15:04 +0100 Subject: use table.orderpair to ensure dependency order stay the same --- xmake/rules/c++/modules/modules_support/builder.lua | 2 +- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index db986b4ff..9f695cede 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -101,7 +101,7 @@ function _should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt local requires = opt.requires if requires then - for required, _ in pairs(requires) do + for required, _ in table.orderpairs(requires) do local m = get_from_target_mapper(target, required) if m then local rebuild = compiler_support.memcache():get2("should_build_in" .. target:name(), m.key) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 8b62069b9..7b382e130 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -129,7 +129,7 @@ function _get_maplines(target, module) table.insert(maplines, m_name .. " " .. compiler_support.get_bmi_path(m.bmi)) end - for required, _ in pairs(module.requires) do + for required, _ in table.orderpairs(module.requires) do local dep_module local dep_target for _, dep in ipairs(target:orderdeps()) do -- cgit v1.3.1 From 7d5573aa4d49f00e0b3420230841d25c4275f48b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 31 Jan 2024 17:16:36 +0100 Subject: optimise header duplication detection --- xmake/rules/c++/modules/modules_support/builder.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 9f695cede..f92f2ed7e 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -168,10 +168,10 @@ function _target_module_map_cachekey(target) end function _is_duplicated_headerunit(target, key) - local mapper = get_target_module_mapper(target) - for _, mapped in pairs(mapper) do - if mapped.key == key then - return mapped + local mapper, mapper_keys = get_target_module_mapper(target) + for _, mapped_key in ipairs(mapper_keys) do + if mapped_key == key then + return mapper[mapped_key] end end end @@ -338,7 +338,7 @@ function get_target_module_mapper(target) memcache:set2(target:name(), "module_mapper", mapper) end - return mapper + return mapper, table.keys(mapper) end -- get a module or headerunit from target mapper -- cgit v1.3.1 From a204e49f7d3d39e27e621b3c5eb241c0021497a5 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 2 Feb 2024 22:52:44 +0800 Subject: format some codes --- .../rules/c++/modules/modules_support/builder.lua | 9 +---- .../c++/modules/modules_support/clang/builder.lua | 21 ++-------- .../modules/modules_support/compiler_support.lua | 2 +- .../modules/modules_support/dependency_scanner.lua | 47 +++------------------- xmake/rules/c++/modules/xmake.lua | 4 +- 5 files changed, 13 insertions(+), 70 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index f92f2ed7e..c58f19510 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -153,12 +153,11 @@ function _generate_meta_module_info(target, name, sourcefile, requires) -- add imports if requires then - for _name, _ in pairs(requires) do + for _name, _ in table.orderpairs(requires) do module_metadata.imports = module_metadata.imports or {} table.append(module_metadata.imports, _name) end end - return module_metadata end @@ -177,7 +176,6 @@ function _is_duplicated_headerunit(target, key) end function _builder(target) - local cachekey = tostring(target) local builder = compiler_support.memcache():get2("builder", cachekey) if builder == nil then @@ -212,7 +210,6 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op batchjobs:group_enter(target:name() .. "/build_modules", {rootjob = opt.rootjob}) local modulesjobs = {} - _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(deps, build, module, name, provide, objectfile, cppfile, fileconfig) local job_name = name and target:name() .. name or cppfile @@ -268,6 +265,7 @@ function build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules if not user_headerunits and not stl_headerunits then return end + -- we need new group(headerunits) -- e.g. group(build_modules) -> group(headerunits) opt.rootjob = batchjobs:group_leave() or opt.rootjob @@ -329,15 +327,12 @@ end -- get or create a target module mapper function get_target_module_mapper(target) - - opt = opt or {} local memcache = compiler_support.memcache() local mapper = memcache:get2(target:name(), "module_mapper") if not mapper then mapper = {} memcache:set2(target:name(), "module_mapper", mapper) end - return mapper, table.keys(mapper) end diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 64243fd3f..d84bb0cd6 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -43,7 +43,6 @@ function _make_modulebuildflags(target, provide, bmifile, opt) elseif provide then -- two step compilation of named module precompile = true flags = {{"-x", "c++-module", "--precompile"}} - if not opt.external then table.insert(flags, {}) end @@ -68,11 +67,8 @@ function _make_headerunitflags(target, headerunit, bmifile) assert(module_headerflag, "compiler(clang): does not support c++ header units!") local local_directory = (headerunit.type == ":quote") and {"-I" .. path.directory(headerunit.path)} or {} - local headertype = (headerunit.type == ":angle") and "system" or "user" - local flags = table.join(local_directory, {"-xc++-header", "-Wno-everything", module_headerflag .. headertype}) - return flags end @@ -90,8 +86,8 @@ function _compile(target, flags, sourcefile, outputfile, opt) print(compinst:compcmd(opt.bmifile or sourcefile, outputfile, {target = target, compflags = flags, rawargs = true})) end + -- do compile if not dryrun then - -- do compile assert(compinst:compile(opt.bmifile or sourcefile, outputfile, {target = target, compflags = flags})) end end @@ -119,7 +115,6 @@ end function _get_requiresflags(target, module, opt) local modulefileflag = compiler_support.get_modulefileflag(target) - local name = module.name local cachekey = target:name() .. name @@ -130,11 +125,10 @@ function _get_requiresflags(target, module, opt) requiresflags = {} for required, _ in table.orderpairs(module.requires) do local dep_module = get_from_target_mapper(target, required) - assert(dep_module, "module dependency %s required for %s not found", required, name) - local bmifile = dep_module.bmi -- aliased headerunit + local bmifile = dep_module.bmi if dep_module.aliasof then local aliased = get_from_target_mapper(target, dep_module.aliasof) bmifile = aliased.bmi @@ -151,15 +145,12 @@ function _get_requiresflags(target, module, opt) compiler_support.memcache():set2(cachekey, "requiresflags", table.unique(requiresflags)) compiler_support.localcache():set2(cachekey, "requiresflags", table.unique(requiresflags)) end - return requiresflags end function _append_requires_flags(target, module, name, cppfile, bmifile, opt) - local cxxflags = {} local requiresflags = _get_requiresflags(target, {name = (name or cppfile), bmi = bmifile, requires = module.requires}, {regenerate = opt.build}) - for _, flag in ipairs(requiresflags) do -- we need to wrap flag to support flag with space if type(flag) == "string" and flag:find(" ", 1, true) then @@ -171,11 +162,10 @@ function _append_requires_flags(target, module, name, cppfile, bmifile, opt) target:fileconfig_add(cppfile, {force = {cxxflags = cxxflags}}) end --- populate module map +-- populate module map function populate_module_map(target, modules) local clang_version = compiler_support.get_clang_version(target) local support_namedmodule = semver.compare(clang_version, "16.0") >= 0 - for _, module in pairs(modules) do local name, provide, cppfile = compiler_support.get_provided_module(module) if provide then @@ -190,14 +180,12 @@ function get_module_required_defines(target, sourcefile) local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) local defines - for _, flag in ipairs(compflags) do if flag:startswith("-D") then defines = defines or {} table.insert(defines, flag:sub(3)) end end - return defines end @@ -322,9 +310,7 @@ end -- build headerunit file for batchcmds function make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, opt) - batchcmds:mkdir(outputdir) - add_headerunit_to_target_mapper(target, headerunit, bmifile) if opt.build then @@ -337,7 +323,6 @@ function make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outp end function get_requires(target, module) - local _requires local flags = _get_requiresflags(target, module) for _, flag in ipairs(flags) do diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua index 3bf89b885..52ee86a57 100644 --- a/xmake/rules/c++/modules/modules_support/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua @@ -242,7 +242,7 @@ function get_provided_module(module) local name, provide, cppfile if module.provides then - -- assume there that provides is only one, until we encounter the cases + -- assume there that provides is only one, until we encounter the cases -- "Some compiler may choose to implement the :private module partition as a separate module for lookup purposes, and if so, it should be indicated as a separate provides entry." local length = 0 for k, v in pairs(module.provides) do diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index 830263d07..46d53577a 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -69,7 +69,6 @@ function _parse_meta_info(target, metafile) break end end - return filename, name, metadata end @@ -449,23 +448,21 @@ end -- extract packages modules dependencies function get_all_packages_modules(target, opt) - local packages_modules -- parse all meta-info and append their informations to the package store local packages = target:pkgs() or {} - - for _, deps in pairs(target:orderdeps()) do + for _, deps in ipairs(target:orderdeps()) do table.join2(packages, deps:pkgs()) end - for _, package in pairs(packages) do + local packages_modules + for _, package in table.orderpairs(packages) do local package_modules = _get_package_modules(target, package, opt) if package_modules then packages_modules = packages_modules or {} table.join2(packages_modules, package_modules) end end - return packages_modules end @@ -511,40 +508,6 @@ end -- when building a library we only cull external modules because we need module objectfiles to be linked inside the library -- on an executable we cull explicitly referenced module function cull_unused_modules(target, modules) - - local cull_all_modules = target:kind() == "executable" - - local needed_modules = {} - for _, module in pairs(modules) do - local fileconfig = target:fileconfig(module.sourcefile) - local external = fileconfig and fileconfig.external - if not (cull_all_modules and external) then - goto CONTINUE - end - - if module.provides and module.requires then - table.join2(needed_modules, _fill_needed_module(target, modules, module)) - end - - ::CONTINUE:: - end - - local culled = {} - for objectfile, module in pairs(modules) do - -- if cull_all_modules and modules.provides then - -- local name,_,_ = compiler_support.get_provided_module(module) - -- if module.requires then - -- for required, _ in pairs(module.requires) do - -- table.insert(needed_modules, required) - -- end - -- end - -- if table.find(needed_modules, name) then - -- culled[objectfile] = module - -- end - -- else - culled[objectfile] = module - -- end - end - - return culled + -- TODO + return modules end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 56ec15343..13f248880 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -82,7 +82,7 @@ rule("c++.build.modules.builder") local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) if package_modules_data then -- append to sourcebatch - for _, package_module_data in pairs(package_modules_data) do + for _, package_module_data in table.orderpairs(package_modules_data) do table.insert(sourcebatch.sourcefiles, package_module_data.file) target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) end @@ -129,7 +129,7 @@ rule("c++.build.modules.builder") local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) if package_modules_data then -- append to sourcebatch - for _, package_module_data in pairs(package_modules_data) do + for _, package_module_data in table.orderpairs(package_modules_data) do table.insert(sourcebatch.sourcefiles, package_module_data.file) target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) end -- cgit v1.3.1 From 0e13da284bcf633da644d680fbc33f246124eda4 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 2 Feb 2024 22:53:07 +0800 Subject: rename apis --- xmake/rules/c++/modules/modules_support/builder.lua | 8 ++++---- xmake/rules/c++/modules/modules_support/clang/builder.lua | 8 ++++---- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 8 ++++---- xmake/rules/c++/modules/modules_support/msvc/builder.lua | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index c58f19510..5117b3a2c 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -214,7 +214,7 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op build_module = function(deps, build, module, name, provide, objectfile, cppfile, fileconfig) local job_name = name and target:name() .. name or cppfile - modulesjobs[job_name] = _builder(target).make_module_build_job(target, batchjobs, job_name, deps, {build = build, module = module, objectfile = objectfile, cppfile = cppfile}) + modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {build = build, module = module, objectfile = objectfile, cppfile = cppfile}) if provide and fileconfig and fileconfig.public then batchjobs:addjob(name .. "_metafile", function(index, total) @@ -242,7 +242,7 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(_, build, module, name, provide, objectfile, cppfile, fileconfig) - depmtime = math.max(depmtime, _builder(target).make_module_build_cmds(target, batchcmds, {build = build, module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) + depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {build = build, module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) if provide and fileconfig and fileconfig.public then local metafilepath = compiler_support.get_metafile(target, cppfile) @@ -276,7 +276,7 @@ function build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules _build_headerunits(target, headerunits, table.join(opt, { build_headerunit = function(headerunit, key, bmifile, outputdir, build) local job_name = target:name() .. key - local job = _builder(target).make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, table.join(opt, {build = build})) + local job = _builder(target).make_headerunit_buildjobs(target, job_name, batchjobs, headerunit, bmifile, outputdir, table.join(opt, {build = build})) if job then modulesjobs[job_name] = job end @@ -308,7 +308,7 @@ function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules local depmtime = 0 _build_headerunits(target, headerunits, table.join(opt, { build_headerunit = function(headerunit, _, bmifile, outputdir, build) - depmtime = math.max(depmtime, _builder(target).make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, table.join({build = build}, opt))) + depmtime = math.max(depmtime, _builder(target).make_headerunit_buildcmds(target, batchcmds, headerunit, bmifile, outputdir, table.join({build = build}, opt))) end })) batchcmds:set_depmtime(depmtime) diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index d84bb0cd6..b9054dabf 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -190,7 +190,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_build_job(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -245,7 +245,7 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_build_cmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -276,7 +276,7 @@ function make_module_build_cmds(target, batchcmds, opt) end -- build headerunit file for batchjobs -function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildjobs(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) local already_exists = add_headerunit_to_target_mapper(target, headerunit, bmifile) if not already_exists then @@ -309,7 +309,7 @@ function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmif end -- build headerunit file for batchcmds -function make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildcmds(target, batchcmds, headerunit, bmifile, outputdir, opt) batchcmds:mkdir(outputdir) add_headerunit_to_target_mapper(target, headerunit, bmifile) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index f0599c7f2..a82c779a2 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -226,7 +226,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_build_job(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -273,7 +273,7 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_build_cmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local module_mapperflag = compiler_support.get_modulemapperflag(target) @@ -304,7 +304,7 @@ function make_module_build_cmds(target, batchcmds, opt) end -- build headerunit file for batchjobs -function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildjobs(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) local _headerunit = headerunit _headerunit.path = headerunit.type == ":quote" and "./" .. path.relative(headerunit.path) or headerunit.path @@ -345,7 +345,7 @@ function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmif end -- build headerunit file for batchcmds -function make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildcmds(target, batchcmds, headerunit, bmifile, outputdir, opt) local headerunit_mapper = _generate_headerunit_modulemapper_file({name = path.normalize(headerunit.path), bmifile = bmifile}) batchcmds:mkdir(outputdir) diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 824989777..cca964c58 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -204,7 +204,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_build_job(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -254,7 +254,7 @@ function make_module_build_job(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_build_cmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -281,7 +281,7 @@ function make_module_build_cmds(target, batchcmds, opt) end -- build headerunit file for batchjobs -function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildjobs(target, job_name, batchjobs, headerunit, bmifile, outputdir, opt) local already_exists = add_headerunit_to_target_mapper(target, headerunit, bmifile) if not already_exists then @@ -316,7 +316,7 @@ function make_headerunit_build_job(target, job_name, batchjobs, headerunit, bmif end -- build headerunit file for batchcmds -function make_headerunit_build_cmds(target, batchcmds, headerunit, bmifile, outputdir, opt) +function make_headerunit_buildcmds(target, batchcmds, headerunit, bmifile, outputdir, opt) batchcmds:mkdir(outputdir) -- cgit v1.3.1 From e449836c75d31664d14ad237c65d8416447bbf87 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 2 Feb 2024 22:57:29 +0800 Subject: improve _is_duplicated_headerunit --- .../rules/c++/modules/modules_support/builder.lua | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 5117b3a2c..741009af5 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -167,12 +167,8 @@ function _target_module_map_cachekey(target) end function _is_duplicated_headerunit(target, key) - local mapper, mapper_keys = get_target_module_mapper(target) - for _, mapped_key in ipairs(mapper_keys) do - if mapped_key == key then - return mapper[mapped_key] - end - end + local _, mapper_keys = get_target_module_mapper(target) + return mapper_keys[key] end function _builder(target) @@ -325,6 +321,12 @@ function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules end end +-- flush target module mapper keys +function flush_target_module_mapper_keys(target) + local memcache = compiler_support.memcache() + memcache:set2(target:name(), "module_mapper_keys", nil) +end + -- get or create a target module mapper function get_target_module_mapper(target) local memcache = compiler_support.memcache() @@ -333,7 +335,19 @@ function get_target_module_mapper(target) mapper = {} memcache:set2(target:name(), "module_mapper", mapper) end - return mapper, table.keys(mapper) + + -- we generate the keys map to optimise the efficiency of _is_duplicated_headerunit + local mapper_keys = memcache:get2(target:name(), "module_mapper_keys") + if not mapper_keys then + mapper_keys = {} + for _, item in pairs(mapper) do + if item.key then + mapper_keys[item.key] = item + end + end + memcache:set2(target:name(), "module_mapper_keys", mapper_keys) + end + return mapper, mapper_keys end -- get a module or headerunit from target mapper @@ -348,6 +362,7 @@ end function add_module_to_target_mapper(target, name, sourcefile, bmifile, opt) local mapper = get_target_module_mapper(target) mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} + flush_target_module_mapper_keys(target) end -- add a headerunit to target mapper @@ -360,6 +375,7 @@ function add_headerunit_to_target_mapper(target, headerunit, bmifile) else mapper[headerunit.name] = {name = headerunit.name, key = key, headerunit = headerunit, bmi = bmifile} end + flush_target_module_mapper_keys(target) return deduplicated and true or false end -- cgit v1.3.1 From a393c0a2d41c22514769ec270818a599c2b9008f Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 3 Feb 2024 19:45:17 +0100 Subject: fix recompilation of .cpp files --- .../rules/c++/modules/modules_support/builder.lua | 37 ++++------- .../c++/modules/modules_support/clang/builder.lua | 74 ++++++++++++++-------- .../c++/modules/modules_support/gcc/builder.lua | 24 ++++++- .../c++/modules/modules_support/msvc/builder.lua | 52 ++++++++++----- 4 files changed, 120 insertions(+), 67 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 741009af5..a4bbc9c7f 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -47,24 +47,17 @@ function _build_modules(target, sourcebatch, modules, opt) local fileconfig = target:fileconfig(cppfile) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) - local build = _should_build(target, cppfile, bmifile, {objectfile = objectfile, requires = module.requires}) - -- add objectfile if module is not from external dep if not (fileconfig and fileconfig.external) then target:add("objectfiles", objectfile) end - -- needed to detect rebuild of dependencies - if provide and build then - _mark_build(target, name) - end - local deps = {} for _, dep in ipairs(table.keys(module.requires or {})) do table.insert(deps, opt.batchjobs and target:name() .. dep or dep) end - opt.build_module(deps, build, module, name, provide, objectfile, cppfile, fileconfig) + opt.build_module(deps, module, name, provide, objectfile, cppfile, fileconfig) ::CONTINUE:: end @@ -112,23 +105,21 @@ function _should_build(target, sourcefile, bmifile, opt) end end - -- or rebuild it if the file changed for headerunit and namedmodules + -- or rebuild it if the file changed local objectfile = opt.objectfile - if compiler_support.has_module_extension(sourcefile) or (opt and opt.headerunit) then - local dryrun = option.get("dry-run") - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) + local dryrun = option.get("dry-run") + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) - local dependfile = target:dependfile(bmifile or objectfile) - local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) + local dependfile = target:dependfile(bmifile or objectfile) + local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) - -- need build this object? - local depvalues = {compinst:program(), compflags} - local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 + -- need build this object? + local depvalues = {compinst:program(), compflags} + local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 - if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then - return true - end + if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then + return true end return false @@ -207,10 +198,10 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op local modulesjobs = {} _build_modules(target, sourcebatch, modules, table.join(opt, { - build_module = function(deps, build, module, name, provide, objectfile, cppfile, fileconfig) + build_module = function(deps, module, name, provide, objectfile, cppfile, fileconfig) local job_name = name and target:name() .. name or cppfile - modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {build = build, module = module, objectfile = objectfile, cppfile = cppfile}) + modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, _should_build, _mark_build, {module = module, objectfile = objectfile, cppfile = cppfile}) if provide and fileconfig and fileconfig.public then batchjobs:addjob(name .. "_metafile", function(index, total) diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 86b3d1a37..8b1cdf827 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -190,7 +190,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -210,31 +210,42 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} local depvalues = {compinst:program(), compflags} - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then - local objectdir = path.directory(opt.objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) + if not dryrun then + local objectdir = path.directory(opt.objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end end - end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.external - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, external = external, name = name}) + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, external = external, name = name}) - _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) + _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - if second_step then - _compile(target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + if second_step then + _compile(target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + end + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files end end @@ -245,7 +256,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -255,19 +266,30 @@ function make_module_buildcmds(target, batchcmds, opt) _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - batchcmds:mkdir(path.directory(opt.objectfile)) + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + batchcmds:mkdir(path.directory(opt.objectfile)) + + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.external - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) - _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) + _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - if second_step then - _batchcmds_compile(batchcmds, target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + if second_step then + _batchcmds_compile(batchcmds, target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + end + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 2f763744a..c90fe743e 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -207,7 +207,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -229,6 +229,13 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} @@ -245,6 +252,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local flags = _make_modulebuildflags(target, opt) _compile(target, flags, opt.cppfile, opt.objectfile) os.tryrm(module_mapper) + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files end end table.insert(dependinfo.files, opt.cppfile) @@ -254,7 +263,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local module_mapperflag = compiler_support.get_modulemapperflag(target) @@ -266,7 +275,14 @@ function make_module_buildcmds(target, batchcmds, opt) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end - if opt.build then + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + + if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) @@ -275,6 +291,8 @@ function make_module_buildcmds(target, batchcmds, opt) end batchcmds:mkdir(path.directory(opt.objectfile)) _batchcmds_compile(batchcmds, target, _make_modulebuildflags(target, {batchcmds = true, sourcefile = opt.cppfile}), opt.cppfile, opt.objectfile) + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile) diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 019235837..925f0fa35 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -207,7 +207,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -227,27 +227,39 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} local depvalues = {compinst:program(), compflags} - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then - local objectdir = path.directory(opt.objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) + if not dryrun then + local objectdir = path.directory(opt.objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end end - end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external - local flags = _make_modulebuildflags(target, provide, bmifile, {external = external}) + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.external + local flags = _make_modulebuildflags(target, provide, bmifile, {external = external}) - _compile(target, flags, opt.cppfile, opt.objectfile) + _compile(target, flags, opt.cppfile, opt.objectfile) + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files + end end table.insert(dependinfo.files, opt.cppfile) @@ -257,7 +269,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -267,7 +279,15 @@ function make_module_buildcmds(target, batchcmds, opt) _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end - if opt.build then + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + + if build then + -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) @@ -276,6 +296,8 @@ function make_module_buildcmds(target, batchcmds, opt) local external = fileconfig and fileconfig.external local flags = _make_modulebuildflags(target, provide, bmifile, opt.cppfile, opt.objectfile, {batchcmds = true, external = external}) _batchcmds_compile(batchcmds, target, flags, opt.cppfile, objectfile) + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile) -- cgit v1.3.1 From ce79b0d86208463a6a6fded2131baf72247526d1 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 3 Feb 2024 22:32:33 +0100 Subject: fix batchcmds --- xmake/rules/c++/modules/modules_support/builder.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index a4bbc9c7f..93ecebe08 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -228,8 +228,8 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { - build_module = function(_, build, module, name, provide, objectfile, cppfile, fileconfig) - depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {build = build, module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) + build_module = function(_, module, name, provide, objectfile, cppfile, fileconfig) + depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, _should_build, _mark_build, {module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) if provide and fileconfig and fileconfig.public then local metafilepath = compiler_support.get_metafile(target, cppfile) -- cgit v1.3.1 From e5f820e4f187e2a87db4b88c76cc2ac3da2b24d7 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 4 Feb 2024 16:44:22 +0100 Subject: make should_build and mark_build public --- xmake/rules/c++/modules/modules_support/builder.lua | 12 ++++++------ xmake/rules/c++/modules/modules_support/clang/builder.lua | 4 ++-- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 4 ++-- xmake/rules/c++/modules/modules_support/msvc/builder.lua | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 93ecebe08..4ceb67b0b 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -78,10 +78,10 @@ function _build_headerunits(target, headerunits, opt) end local bmifile = path.join(outputdir, path.filename(headerunit.name) .. compiler_support.get_bmi_extension(target)) local key = path.normalize(headerunit.path) - local build = _should_build(target, headerunit.path, bmifile, {key = key, headerunit = true}) + local build = should_build(target, headerunit.path, bmifile, {key = key, headerunit = true}) if build then - _mark_build(target, key) + mark_build(target, key) end opt.build_headerunit(headerunit, key, bmifile, outputdir, build) @@ -89,7 +89,7 @@ function _build_headerunits(target, headerunits, opt) end -- should we build this module or headerunit ? -function _should_build(target, sourcefile, bmifile, opt) +function should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt local requires = opt.requires @@ -181,7 +181,7 @@ function _builder(target) return builder end -function _mark_build(target, name) +function mark_build(target, name) compiler_support.memcache():set2("should_build_in" .. target:name(), name, true) end @@ -201,7 +201,7 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op build_module = function(deps, module, name, provide, objectfile, cppfile, fileconfig) local job_name = name and target:name() .. name or cppfile - modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, _should_build, _mark_build, {module = module, objectfile = objectfile, cppfile = cppfile}) + modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {module = module, objectfile = objectfile, cppfile = cppfile}) if provide and fileconfig and fileconfig.public then batchjobs:addjob(name .. "_metafile", function(index, total) @@ -229,7 +229,7 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(_, module, name, provide, objectfile, cppfile, fileconfig) - depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, _should_build, _mark_build, {module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) + depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) if provide and fileconfig and fileconfig.public then local metafilepath = compiler_support.get_metafile(target, cppfile) diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 9643fe84e..0d470ada4 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -190,7 +190,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -263,7 +263,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) +function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index ae3ed2d95..db0ea3958 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -207,7 +207,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) @@ -263,7 +263,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) +function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 3a4b14b68..4aa353214 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -207,7 +207,7 @@ function get_module_required_defines(target, sourcefile) end -- build module file for batchjobs -function make_module_buildjobs(target, batchjobs, job_name, deps, should_build, mark_build, opt) +function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) -- cgit v1.3.1 From 4a6acafb07f5af250c51604c731dba7fafdd8547 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 4 Feb 2024 17:50:55 +0100 Subject: fix objectfile handling --- xmake/rules/c++/modules/modules_support/builder.lua | 1 - .../rules/c++/modules/modules_support/clang/builder.lua | 16 ++++++++-------- .../c++/modules/modules_support/compiler_support.lua | 16 +++++++++++----- .../c++/modules/modules_support/dependency_scanner.lua | 5 +++-- xmake/rules/c++/modules/modules_support/msvc/builder.lua | 14 ++++++-------- xmake/rules/c++/modules/xmake.lua | 4 ++-- 6 files changed, 30 insertions(+), 26 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 4ceb67b0b..ca7a3cbb8 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -32,7 +32,6 @@ import("dependency_scanner") -- build target modules function _build_modules(target, sourcebatch, modules, opt) local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) - _builder(target).populate_module_map(target, modules) -- build modules diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 15a53c00b..6a7237eb2 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -38,12 +38,12 @@ function _make_modulebuildflags(target, provide, bmifile, opt) local flags local precompile = false - if module_outputflag and provide and not opt.external then -- one step compilation of named module, clang >= 16 + if module_outputflag and provide and opt.build_objectfile then -- one step compilation of named module, clang >= 16 flags = {{"-x", "c++-module", module_outputflag .. bmifile}} elseif provide then -- two step compilation of named module precompile = true flags = {{"-x", "c++-module", "--precompile"}} - if not opt.external then + if opt.build_objectfile then table.insert(flags, {}) end else -- internal module, no bmi needed @@ -199,7 +199,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) return { name = job_name, deps = deps, - sourcefile = cppfile, + sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) local compinst = compiler.load("cxx", {target = target}) @@ -242,10 +242,9 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + local build_objectfile = target:kind() == "binary" - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, external = external, name = name}) + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) @@ -289,14 +288,15 @@ function make_module_buildcmds(target, batchcmds, opt) build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) end + local build_objectfile = target:kind() == "binary" if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) + _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua index 52ee86a57..8c03c9dba 100644 --- a/xmake/rules/c++/modules/modules_support/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua @@ -64,14 +64,20 @@ function patch_sourcebatch(target, sourcebatch) end -- cull sourcebatch objectfiles -function cull_objectfiles(target, sourcebatch) +function cull_objectfiles(target, modules, sourcebatch) + + -- don't cull for executables + if target:kind() == "binary" then + return + end - sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local fileconfig = target:fileconfig(sourcefile) - if not (fileconfig and fileconfig.external) then - local objectfile = target:objectfile(sourcefile) + local objectfile = target:objectfile(sourcefile) + local module = modules[objectfile] + local _, provide, _ = get_provided_module(module) + + if not provide then table.insert(sourcebatch.objectfiles, objectfile) end end diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index 7ad344750..82e960827 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -182,7 +182,7 @@ function _get_edges(nodes, modules) for _, required_node in ipairs(nodes) do local name, _, _ = compiler_support.get_provided_module(modules[required_node]) if name and name == required_name then - table.insert(edges, {node, required_node}) + table.insert(edges, {required_node, node}) break end end @@ -398,7 +398,7 @@ end -- topological sort function sort_modules_by_dependencies(objectfiles, modules) local result = {} - local edges, nodeps_nodes = _get_edges(objectfiles, modules) + local edges = _get_edges(objectfiles, modules) local dag = graph.new(true) for _, e in ipairs(edges) do dag:add_edge(e[1], e[2]) @@ -418,6 +418,7 @@ function sort_modules_by_dependencies(objectfiles, modules) for _, objectfile in ipairs(objectfiles_sorted) do table.insert(result, objectfile) end + local objectfiles_sorted_set = hashset.from(objectfiles_sorted) for _, objectfile in ipairs(objectfiles) do if not objectfiles_sorted_set:has(objectfile) then diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 10a0ad409..e7b2c8543 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -37,7 +37,7 @@ function _make_modulebuildflags(target, provide, bmifile, opt) local ifconlyflag = compiler_support.get_ifconlyflag(target) local interfaceflag = compiler_support.get_interfaceflag(target) local internalpartitionflag = compiler_support.get_internalpartitionflag(target) - local ifconly = (opt.external and ifconlyflag) + local ifconly = (not opt.build_objectfile and ifconlyflag) local flags if provide then -- named module @@ -259,9 +259,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external - local flags = _make_modulebuildflags(target, provide, bmifile, {external = external}) + local build_objectfile = target:kind() == "binary" + local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile}) _compile(target, flags, opt.cppfile, opt.objectfile) else @@ -307,10 +306,9 @@ function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external - local flags = _make_modulebuildflags(target, provide, bmifile, opt.cppfile, opt.objectfile, {batchcmds = true, external = external}) - _batchcmds_compile(batchcmds, target, flags, opt.cppfile, objectfile) + local build_objectfile = target:kind() == "binary" + local flags = _make_modulebuildflags(target, provide, bmifile, opt.cppfile, {batchcmds = true, build_objectfile = build_objectfile}) + _batchcmds_compile(batchcmds, target, flags, opt.cppfile, opt.objectfile) else batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index ecb79f65b..d9e26e41f 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -100,7 +100,7 @@ rule("c++.build.modules.builder") builder.build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) -- cull external modules objectfile - compiler_support.cull_objectfiles(target, sourcebatch) + compiler_support.cull_objectfiles(target, modules, sourcebatch) else -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} @@ -147,7 +147,7 @@ rule("c++.build.modules.builder") builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cull external modules objectfile - compiler_support.cull_objectfiles(target, sourcebatch) + compiler_support.cull_objectfiles(target, modules, sourcebatch) else -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} -- cgit v1.3.1 From 2328ca4f94c6a7680c72fc92f43a39c4f753d7a3 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 4 Feb 2024 20:24:24 +0100 Subject: fix missing objectfiles for private modules --- xmake/rules/c++/modules/modules_support/builder.lua | 5 ----- .../c++/modules/modules_support/clang/builder.lua | 14 +++++++++++--- .../c++/modules/modules_support/compiler_support.lua | 9 ++++++++- .../rules/c++/modules/modules_support/msvc/builder.lua | 10 ++++++++-- xmake/rules/c++/modules/xmake.lua | 18 ++++++++++++++---- 5 files changed, 41 insertions(+), 15 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index ca7a3cbb8..62b874bfb 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -45,11 +45,6 @@ function _build_modules(target, sourcebatch, modules, opt) cppfile = cppfile or module.cppfile local fileconfig = target:fileconfig(cppfile) - local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) - -- add objectfile if module is not from external dep - if not (fileconfig and fileconfig.external) then - target:add("objectfiles", objectfile) - end local deps = {} for _, dep in ipairs(table.keys(module.requires or {})) do diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 6a7237eb2..5050be7cf 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -242,7 +242,10 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local build_objectfile = target:kind() == "binary" + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local build_objectfile = target:kind() == "binary" or (not public and not external) local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) @@ -295,8 +298,13 @@ function make_module_buildcmds(target, batchcmds, opt) batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) - _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local build_objectfile = target:kind() == "binary" or (not public and not external) + + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) + _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua index 8c03c9dba..d9d849454 100644 --- a/xmake/rules/c++/modules/modules_support/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua @@ -77,7 +77,14 @@ function cull_objectfiles(target, modules, sourcebatch) local module = modules[objectfile] local _, provide, _ = get_provided_module(module) - if not provide then + if provide then + local fileconfig = target:fileconfig(sourcefile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + if not public and not external then + table.insert(sourcebatch.objectfiles, objectfile) + end + else table.insert(sourcebatch.objectfiles, objectfile) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index e7b2c8543..702f3f2f2 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -259,7 +259,10 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local build_objectfile = target:kind() == "binary" + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local build_objectfile = target:kind() == "binary" or (not public and not external) local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile}) _compile(target, flags, opt.cppfile, opt.objectfile) @@ -306,7 +309,10 @@ function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) - local build_objectfile = target:kind() == "binary" + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local build_objectfile = target:kind() == "binary" or (not public and not external) local flags = _make_modulebuildflags(target, provide, bmifile, opt.cppfile, {batchcmds = true, build_objectfile = build_objectfile}) _batchcmds_compile(batchcmds, target, flags, opt.cppfile, opt.objectfile) else diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index d9e26e41f..96446e2ec 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -76,7 +76,12 @@ rule("c++.build.modules.builder") end -- append std module - table.join2(sourcebatch.sourcefiles, compiler_support.get_stdmodules(target) or {}) + local std_modules = compiler_support.get_stdmodules(target) + if std_modules then + table.join2(sourcebatch.sourcefiles, std_modules) + target:fileconfig_set(std_modules[1], {external = true}) + target:fileconfig_set(std_modules[2], {external = true}) + end -- extract packages modules dependencies local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) @@ -84,7 +89,7 @@ rule("c++.build.modules.builder") -- append to sourcebatch for _, package_module_data in table.orderpairs(package_modules_data) do table.insert(sourcebatch.sourcefiles, package_module_data.file) - target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) end end @@ -123,7 +128,12 @@ rule("c++.build.modules.builder") end -- append std module - table.join2(sourcebatch.sourcefiles, compiler_support.get_stdmodules(target) or {}) + local std_modules = compiler_support.get_stdmodules(target) + if std_modules then + table.join2(sourcebatch.sourcefiles, std_modules) + target:fileconfig_set(std_modules[1], {external = true}) + target:fileconfig_set(std_modules[2], {external = true}) + end -- extract packages modules dependencies local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) @@ -131,7 +141,7 @@ rule("c++.build.modules.builder") -- append to sourcebatch for _, package_module_data in table.orderpairs(package_modules_data) do table.insert(sourcebatch.sourcefiles, package_module_data.file) - target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) end end -- cgit v1.3.1 From 0b8ea930d1d9cc7dbb38fa62d1331f2addbbdc66 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 5 Feb 2024 16:18:41 +0100 Subject: cull unreferenced modules and fix gcc module mapper --- xmake/rules/c++/modules/modules_support/builder.lua | 2 +- .../c++/modules/modules_support/dependency_scanner.lua | 6 +++++- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 17 ----------------- xmake/rules/c++/modules/xmake.lua | 6 ++++++ 4 files changed, 12 insertions(+), 19 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 62b874bfb..af0a0539f 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -31,7 +31,7 @@ import("dependency_scanner") -- build target modules function _build_modules(target, sourcebatch, modules, opt) - local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + local objectfiles = sourcebatch.objectfiles _builder(target).populate_module_map(target, modules) -- build modules diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index 82e960827..b5b3fcf5f 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -422,7 +422,11 @@ function sort_modules_by_dependencies(objectfiles, modules) local objectfiles_sorted_set = hashset.from(objectfiles_sorted) for _, objectfile in ipairs(objectfiles) do if not objectfiles_sorted_set:has(objectfile) then - table.insert(result, objectfile) + -- cull unreferenced named module but add non-module files + local _, provide, _ = compiler_support.get_provided_module(modules[objectfile]) + if not provide then + table.insert(result, objectfile) + end end end return result diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 7e96c3fcc..17b3aabc5 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -107,13 +107,6 @@ function _get_maplines(target, module) for required, _ in table.orderpairs(module.requires) do local dep_module local dep_target - for _, dep in ipairs(target:orderdeps()) do - dep_module = get_from_target_mapper(dep, required) - if dep_module then - dep_target = dep - break - end - end -- if not in target dep if not dep_module then @@ -173,16 +166,6 @@ end -- populate module map function populate_module_map(target, modules) - - -- append all modules - for _, module in pairs(modules) do - local name, provide = compiler_support.get_provided_module(module) - if provide then - add_module_to_target_mapper(target, name, provide.sourcefile, compiler_support.get_bmi_path(provide.bmi)) - end - end - - -- then update their deps for _, module in pairs(modules) do local name, provide = compiler_support.get_provided_module(module) if provide then diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 96446e2ec..c8385da03 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -98,6 +98,9 @@ rule("c++.build.modules.builder") compiler_support.patch_sourcebatch(target, sourcebatch, opt) local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) + -- avoid linking culled objectfiles + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + -- build modules builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) @@ -150,6 +153,9 @@ rule("c++.build.modules.builder") compiler_support.patch_sourcebatch(target, sourcebatch, opt) local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) + -- avoid linking culled objectfiles + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + -- build headerunits builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cgit v1.3.1 From 6739478d0bf6a4aaf0d1a1caf1c6b60532fa07f8 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 5 Feb 2024 17:30:32 +0100 Subject: fix gcc --- xmake/rules/c++/modules/modules_support/builder.lua | 3 +-- .../c++/modules/modules_support/dependency_scanner.lua | 10 ++++++---- .../rules/c++/modules/modules_support/gcc/builder.lua | 18 ++++-------------- xmake/rules/c++/modules/xmake.lua | 10 +++++----- 4 files changed, 16 insertions(+), 25 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index af0a0539f..1f014abde 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -44,13 +44,12 @@ function _build_modules(target, sourcebatch, modules, opt) local name, provide, cppfile = compiler_support.get_provided_module(module) cppfile = cppfile or module.cppfile - local fileconfig = target:fileconfig(cppfile) - local deps = {} for _, dep in ipairs(table.keys(module.requires or {})) do table.insert(deps, opt.batchjobs and target:name() .. dep or dep) end + local fileconfig = target:fileconfig(cppfile) opt.build_module(deps, module, name, provide, objectfile, cppfile, fileconfig) ::CONTINUE:: diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index b5b3fcf5f..0b02292ef 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -396,7 +396,7 @@ function get_all_packages_modules(target, opt) end -- topological sort -function sort_modules_by_dependencies(objectfiles, modules) +function sort_modules_by_dependencies(target, objectfiles, modules) local result = {} local edges = _get_edges(objectfiles, modules) local dag = graph.new(true) @@ -422,9 +422,11 @@ function sort_modules_by_dependencies(objectfiles, modules) local objectfiles_sorted_set = hashset.from(objectfiles_sorted) for _, objectfile in ipairs(objectfiles) do if not objectfiles_sorted_set:has(objectfile) then - -- cull unreferenced named module but add non-module files - local _, provide, _ = compiler_support.get_provided_module(modules[objectfile]) - if not provide then + -- cull unreferenced non-public named module but add non-module files and implementation modules + local _, provide, cppfile = compiler_support.get_provided_module(modules[objectfile]) + local fileconfig = target:fileconfig(cppfile) + local public = fileconfig and fileconfig.public + if not provide or public then table.insert(result, objectfile) end end diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 17b3aabc5..c4c9871e2 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -99,24 +99,14 @@ end function _get_maplines(target, module) local maplines = {} - local m_name, m = compiler_support.get_provided_module(module) + local m_name, m, cppfile = compiler_support.get_provided_module(module) if m then table.insert(maplines, m_name .. " " .. compiler_support.get_bmi_path(m.bmi)) end for required, _ in table.orderpairs(module.requires) do - local dep_module - local dep_target - - -- if not in target dep - if not dep_module then - dep_module = get_from_target_mapper(target, required) - if dep_module then - dep_target = target - end - end - - assert(dep_module, "module dependency %s required for %s not found", required, m_name) + local dep_module = get_from_target_mapper(target, required) + assert(dep_module, "module dependency %s required for %s not found", required, m_name or module.cppfile) local bmifile = dep_module.bmi local mapline @@ -136,7 +126,7 @@ function _get_maplines(target, module) -- append deps if dep_module.opt and dep_module.opt.deps then - local deps = _get_maplines(dep_target, { name = dep_module.name, bmi = bmifile, requires = dep_module.opt.deps }) + local deps = _get_maplines(target, {name = dep_module.name, bmi = bmifile, requires = dep_module.opt.deps}) table.join2(maplines, deps) end end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index c8385da03..62fb37205 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -98,8 +98,8 @@ rule("c++.build.modules.builder") compiler_support.patch_sourcebatch(target, sourcebatch, opt) local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) - -- avoid linking culled objectfiles - sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + -- avoid building non referenced modules + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) -- build modules builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) @@ -153,8 +153,8 @@ rule("c++.build.modules.builder") compiler_support.patch_sourcebatch(target, sourcebatch, opt) local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) - -- avoid linking culled objectfiles - sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules) + -- avoid building non referenced modules + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) -- build headerunits builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) @@ -163,7 +163,7 @@ rule("c++.build.modules.builder") builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cull external modules objectfile - compiler_support.cull_objectfiles(target, modules, sourcebatch) + -- compiler_support.cull_objectfiles(target, modules, sourcebatch) else -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} -- cgit v1.3.1 From 3280d7f327d762491d36d68a7a0d3ecc89bc7a19 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 5 Feb 2024 18:23:08 +0100 Subject: add support of moduleonly targets with c++.moduleonly rule --- .../rules/c++/modules/modules_support/builder.lua | 29 +++ .../modules/modules_support/compiler_support.lua | 4 +- .../modules/modules_support/dependency_scanner.lua | 2 +- xmake/rules/c++/modules/xmake.lua | 218 ++++++++++++++------- 4 files changed, 174 insertions(+), 79 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 1f014abde..b3426736f 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -21,6 +21,7 @@ -- imports import("core.base.json") import("core.base.option") +import("async.runjobs") import("private.async.buildjobs") import("core.tool.compiler") import("core.project.config") @@ -305,6 +306,34 @@ function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules end end +function generate_metadata(target, modules) + local public_modules + + for _, module in pairs(modules) do + local _, _, cppfile = compiler_support.get_provided_module(module) + local fileconfig = target:fileconfig(cppfile) + local public = fileconfig and fileconfig.public + if public then + public_modules = public_modules or {} + table.insert(public_modules, module) + end + end + + if not public_modules then + return + end + + local jobs = option.get("jobs") or os.default_njob() + runjobs(target:name() .. "_install_modules", function(index) + local module = public_modules[index] + local name, _, cppfile = compiler_support.get_provided_module(module) + local metafilepath = compiler_support.get_metafile(target, cppfile) + progress.show((index * 100) / #public_modules, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name) + local metadata = _generate_meta_module_info(target, name, cppfile, module.requires) + json.savefile(metafilepath, metadata) + end, {comax = jobs, total = #public_modules}) +end + -- flush target module mapper keys function flush_target_module_mapper_keys(target) local memcache = compiler_support.memcache() diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua index d9d849454..d7e8a0bd8 100644 --- a/xmake/rules/c++/modules/modules_support/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua @@ -116,14 +116,14 @@ end -- this target contains module files? function contains_modules(target) -- we can not use `"c++.build.builder"`, because it contains sourcekind/cxx. - local target_with_modules = target:sourcebatches()["c++.build.modules"] and true or false + local target_with_modules = (target:sourcebatches()["c++.moduleonly"] or target:sourcebatches()["c++.build.modules"]) and true or false if not target_with_modules then target_with_modules = target:policy("build.c++.modules") end 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++.moduleonly"] or sourcebatches["c++.build.modules"] then target_with_modules = true break end diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index 0b02292ef..e4e6783bd 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -438,7 +438,7 @@ end function get_targetdeps_modules(target) local sourcefiles for _, dep in ipairs(target:orderdeps()) do - local sourcebatch = dep:sourcebatches()["c++.build.modules.builder"] + local sourcebatch = dep:sourcebatches()["c++.moduleonly"] or dep:sourcebatches()["c++.build.modules.builder"] if sourcebatch and sourcebatch.sourcefiles then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local fileconfig = dep:fileconfig(sourcefile) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 62fb37205..6db349873 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,6 +52,14 @@ rule("c++.build.modules") -- mark this target with modules target:data_set("cxx.has_modules", true) + + -- moduleonly modules are implicitly public + if target:rule("c++.moduleonly") then + local sourcebatch = target:sourcebatches()["c++.moduleonly"] + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + target:fileconfig_add(sourcefile, {public = true}) + end + end end end) @@ -62,111 +70,123 @@ rule("c++.build.modules.builder") -- 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.compiler_support") - import("modules_support.dependency_scanner") - import("modules_support.builder") - - -- add target deps modules - if target:orderdeps() then - local deps_sourcefiles = dependency_scanner.get_targetdeps_modules(target) - if deps_sourcefiles then - table.join2(sourcebatch.sourcefiles, deps_sourcefiles) + if not target:rule("c++.moduleonly") then + if target:data("cxx.has_modules") then + import("modules_support.compiler_support") + import("modules_support.dependency_scanner") + import("modules_support.builder") + + -- add target deps modules + if target:orderdeps() then + local deps_sourcefiles = dependency_scanner.get_targetdeps_modules(target) + if deps_sourcefiles then + table.join2(sourcebatch.sourcefiles, deps_sourcefiles) + end end - end - -- append std module - local std_modules = compiler_support.get_stdmodules(target) - if std_modules then - table.join2(sourcebatch.sourcefiles, std_modules) - target:fileconfig_set(std_modules[1], {external = true}) - target:fileconfig_set(std_modules[2], {external = true}) - end + -- append std module + local std_modules = compiler_support.get_stdmodules(target) + if std_modules then + table.join2(sourcebatch.sourcefiles, std_modules) + target:fileconfig_set(std_modules[1], {external = true}) + target:fileconfig_set(std_modules[2], {external = true}) + end - -- extract packages modules dependencies - local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) - if package_modules_data then - -- append to sourcebatch - for _, package_module_data in table.orderpairs(package_modules_data) do - table.insert(sourcebatch.sourcefiles, package_module_data.file) - target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + -- extract packages modules dependencies + local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) + if package_modules_data then + -- append to sourcebatch + for _, package_module_data in table.orderpairs(package_modules_data) do + table.insert(sourcebatch.sourcefiles, package_module_data.file) + target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + end end - end - opt.batchjobs = true + opt.batchjobs = true - compiler_support.patch_sourcebatch(target, sourcebatch, opt) - local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) + compiler_support.patch_sourcebatch(target, sourcebatch, opt) + local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) - -- avoid building non referenced modules - sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) + -- avoid building non referenced modules + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) - -- build modules - builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + -- build modules + builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - -- build headerunits and we need to do it before building modules - builder.build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + -- build headerunits and we need to do it before building modules + builder.build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - -- cull external modules objectfile - compiler_support.cull_objectfiles(target, modules, sourcebatch) + -- cull external modules objectfile + compiler_support.cull_objectfiles(target, modules, sourcebatch) + else + -- avoid duplicate linking of object files of non-module programs + sourcebatch.objectfiles = {} + end else - -- avoid duplicate linking of object files of non-module programs + sourcebatch.sourcefiles = {} sourcebatch.objectfiles = {} + sourcebatch.dependfiles = {} end end, {batch = true}) -- serial compilation only, usually used to support project generator before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) - if target:data("cxx.has_modules") then - import("modules_support.compiler_support") - import("modules_support.dependency_scanner") - import("modules_support.builder") - - -- add target deps modules - if target:orderdeps() then - local deps_sourcefiles = dependency_scanner.get_targetdeps_modules(target) - if deps_sourcefiles then - table.join2(sourcebatch.sourcefiles, deps_sourcefiles) + if not target:rule("c++.moduleonly") then + if target:data("cxx.has_modules") then + import("modules_support.compiler_support") + import("modules_support.dependency_scanner") + import("modules_support.builder") + + -- add target deps modules + if target:orderdeps() then + local deps_sourcefiles = dependency_scanner.get_targetdeps_modules(target) + if deps_sourcefiles then + table.join2(sourcebatch.sourcefiles, deps_sourcefiles) + end end - end - -- append std module - local std_modules = compiler_support.get_stdmodules(target) - if std_modules then - table.join2(sourcebatch.sourcefiles, std_modules) - target:fileconfig_set(std_modules[1], {external = true}) - target:fileconfig_set(std_modules[2], {external = true}) - end + -- append std module + local std_modules = compiler_support.get_stdmodules(target) + if std_modules then + table.join2(sourcebatch.sourcefiles, std_modules) + target:fileconfig_set(std_modules[1], {external = true}) + target:fileconfig_set(std_modules[2], {external = true}) + end - -- extract packages modules dependencies - local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) - if package_modules_data then - -- append to sourcebatch - for _, package_module_data in table.orderpairs(package_modules_data) do - table.insert(sourcebatch.sourcefiles, package_module_data.file) - target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + -- extract packages modules dependencies + local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) + if package_modules_data then + -- append to sourcebatch + for _, package_module_data in table.orderpairs(package_modules_data) do + table.insert(sourcebatch.sourcefiles, package_module_data.file) + target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + end end - end - opt.batchjobs = false + opt.batchjobs = false - compiler_support.patch_sourcebatch(target, sourcebatch, opt) - local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) + compiler_support.patch_sourcebatch(target, sourcebatch, opt) + local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) - -- avoid building non referenced modules - sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) + -- avoid building non referenced modules + sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules) - -- build headerunits - builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + -- build headerunits + builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - -- build modules - builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + -- build modules + builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - -- cull external modules objectfile - -- compiler_support.cull_objectfiles(target, modules, sourcebatch) + -- cull external modules objectfile + -- compiler_support.cull_objectfiles(target, modules, sourcebatch) + else + -- avoid duplicate linking of object files of non-module programs + sourcebatch.objectfiles = {} + end else - -- avoid duplicate linking of object files of non-module programs + sourcebatch.sourcefiles = {} sourcebatch.objectfiles = {} + sourcebatch.dependfiles = {} end end) @@ -187,16 +207,62 @@ rule("c++.build.modules.builder") end end) +-- moduleonly +rule("c++.moduleonly") + add_deps("c++.build.modules.install") + set_extensions(".mpp", ".mxx", ".cppm", ".ixx", ".cpp") + + before_build(function(target) + if target:data("cxx.has_modules") then + import("modules_support.compiler_support") + import("modules_support.dependency_scanner") + + local sourcebatch = target:sourcebatches()["c++.moduleonly"] + + -- add target deps modules + if target:orderdeps() then + local deps_sourcefiles = dependency_scanner.get_targetdeps_modules(target) + if deps_sourcefiles then + table.join2(sourcebatch.sourcefiles, deps_sourcefiles) + end + end + + -- append std module + table.join2(sourcebatch.sourcefiles, compiler_support.get_stdmodules(target) or {}) + + -- extract packages modules dependencies + local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt) + if package_modules_data then + -- append to sourcebatch + for _, package_module_data in table.orderpairs(package_modules_data) do + table.insert(sourcebatch.sourcefiles, package_module_data.file) + target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines}) + end + end + + local opt = {batchjobs = true} + + compiler_support.patch_sourcebatch(target, sourcebatch, opt) + local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt) + compiler_support.localcache():set2(target:name(), "c++.modules", modules) + compiler_support.localcache():save() + end + end) + -- install modules rule("c++.build.modules.install") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") before_install(function (target) import("modules_support.compiler_support") + import("modules_support.builder") -- we cannot use target:data("cxx.has_modules"), -- because on_config will be not called when installing targets if compiler_support.contains_modules(target) then + local modules = compiler_support.localcache():get2(target:name(), "c++.modules") + builder.generate_metadata(target, modules) + compiler_support.install_module_target(target) end end) -- cgit v1.3.1 From cf5c45be7013afc766e63f6d756f32d77ae426cc Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 5 Feb 2024 19:20:53 +0100 Subject: cleanup --- tests/projects/c++/modules/test_base.lua | 2 +- tests/projects/c++/modules/test_stdmodules.lua | 2 +- .../rules/c++/modules/modules_support/builder.lua | 29 +++------------------- 3 files changed, 6 insertions(+), 27 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/tests/projects/c++/modules/test_base.lua b/tests/projects/c++/modules/test_base.lua index f39c31b75..092fbd72f 100644 --- a/tests/projects/c++/modules/test_base.lua +++ b/tests/projects/c++/modules/test_base.lua @@ -56,7 +56,7 @@ function main(t) os.exec("xmake f --toolchain=clang -c --yes") _build() os.exec("xmake clean -a") - os.exec("xmake f --toolchain=clang --runtimes=c++_shared --sdk='/opt/llvm-git/usr/' -c --yes") + os.exec("xmake f --toolchain=clang --runtimes=c++_shared -c --yes") _build() end end diff --git a/tests/projects/c++/modules/test_stdmodules.lua b/tests/projects/c++/modules/test_stdmodules.lua index c29457364..68a5922ef 100644 --- a/tests/projects/c++/modules/test_stdmodules.lua +++ b/tests/projects/c++/modules/test_stdmodules.lua @@ -51,7 +51,7 @@ function main(t) -- os.exec("xmake f --toolchain=clang -c --yes") -- _build() os.exec("xmake clean -a") - os.exec("xmake f --toolchain=clang --runtimes=c++_shared --sdk='/opt/llvm-git/usr/' -c --yes") + os.exec("xmake f --toolchain=clang --runtimes=c++_shared -c --yes") _build() end end diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index b3426736f..768c337ce 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -42,7 +42,7 @@ function _build_modules(target, sourcebatch, modules, opt) goto CONTINUE end - local name, provide, cppfile = compiler_support.get_provided_module(module) + local name, _, cppfile = compiler_support.get_provided_module(module) cppfile = cppfile or module.cppfile local deps = {} @@ -50,8 +50,7 @@ function _build_modules(target, sourcebatch, modules, opt) table.insert(deps, opt.batchjobs and target:name() .. dep or dep) end - local fileconfig = target:fileconfig(cppfile) - opt.build_module(deps, module, name, provide, objectfile, cppfile, fileconfig) + opt.build_module(deps, module, name, objectfile, cppfile) ::CONTINUE:: end @@ -192,21 +191,10 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op local modulesjobs = {} _build_modules(target, sourcebatch, modules, table.join(opt, { - build_module = function(deps, module, name, provide, objectfile, cppfile, fileconfig) + build_module = function(deps, module, name, objectfile, cppfile) local job_name = name and target:name() .. name or cppfile modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {module = module, objectfile = objectfile, cppfile = cppfile}) - - if provide and fileconfig and fileconfig.public then - batchjobs:addjob(name .. "_metafile", function(index, total) - local metafilepath = compiler_support.get_metafile(target, cppfile) - depend.on_changed(function() - progress.show((index * 100) / total, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name) - local metadata = _generate_meta_module_info(target, name, cppfile, module.requires) - json.savefile(metafilepath, metadata) - end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()}) - end, {rootjob = opt.rootjob}) - end end })) @@ -222,17 +210,8 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { - build_module = function(_, module, name, provide, objectfile, cppfile, fileconfig) + build_module = function(_, module, _, objectfile, cppfile) depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) - - if provide and fileconfig and fileconfig.public then - local metafilepath = compiler_support.get_metafile(target, cppfile) - depend.on_changed(function() - progress.show(opt.progress, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name) - local metadata = _generate_meta_module_info(target, name, cppfile, module.requires) - json.savefile(metafilepath, metadata) - end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()}) - end end })) -- cgit v1.3.1 From d98db4c10802a503dd824d0dcb15bacb76d29749 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 7 Feb 2024 11:53:34 +0100 Subject: use table.orderpairs for generate_metadata --- xmake/rules/c++/modules/modules_support/builder.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 768c337ce..936f90414 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -287,8 +287,7 @@ end function generate_metadata(target, modules) local public_modules - - for _, module in pairs(modules) do + for _, module in table.orderpairs(modules) do local _, _, cppfile = compiler_support.get_provided_module(module) local fileconfig = target:fileconfig(cppfile) local public = fileconfig and fileconfig.public -- cgit v1.3.1 From 1a6c4c2a93c80d6ed17a70100f62b221b3730000 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 10 Feb 2024 17:35:35 +0100 Subject: implement module reusage based on flag comparison fix gcc fix msvc fix msvc fix msvc fix --- .../c++/modules/private_module/src/use.cpp | 8 ++ .../c++/modules/private_module/src/use.mpp | 7 +- .../projects/c++/modules/private_module/xmake.lua | 1 + xmake/core/project/policy.lua | 4 + .../rules/c++/modules/modules_support/builder.lua | 90 +++++++++++++- .../c++/modules/modules_support/clang/builder.lua | 132 +++++++++++++-------- .../modules_support/clang/compiler_support.lua | 37 ++++++ .../modules/modules_support/compiler_support.lua | 5 + .../c++/modules/modules_support/gcc/builder.lua | 123 ++++++++++++++----- .../modules_support/gcc/compiler_support.lua | 35 ++++++ .../c++/modules/modules_support/msvc/builder.lua | 116 ++++++++++++++++-- .../modules_support/msvc/compiler_support.lua | 58 +++++++++ 12 files changed, 515 insertions(+), 101 deletions(-) create mode 100644 tests/projects/c++/modules/private_module/src/use.cpp (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/tests/projects/c++/modules/private_module/src/use.cpp b/tests/projects/c++/modules/private_module/src/use.cpp new file mode 100644 index 000000000..f71a3057e --- /dev/null +++ b/tests/projects/c++/modules/private_module/src/use.cpp @@ -0,0 +1,8 @@ +module use; + +import dep1; +import dep2; + +int lib() { + return m() + i(); +} diff --git a/tests/projects/c++/modules/private_module/src/use.mpp b/tests/projects/c++/modules/private_module/src/use.mpp index 8450c341c..33f90c14a 100644 --- a/tests/projects/c++/modules/private_module/src/use.mpp +++ b/tests/projects/c++/modules/private_module/src/use.mpp @@ -1,6 +1,3 @@ -import dep1; -import dep2; +export module use; -int lib() { - return m() + i(); -} \ No newline at end of file +export int lib(); diff --git a/tests/projects/c++/modules/private_module/xmake.lua b/tests/projects/c++/modules/private_module/xmake.lua index 57ede6993..16a2bea92 100644 --- a/tests/projects/c++/modules/private_module/xmake.lua +++ b/tests/projects/c++/modules/private_module/xmake.lua @@ -5,3 +5,4 @@ target("private_module") add_rules("c++") set_kind("$(kind)") add_files("src/*.mpp") + add_files("src/*.cpp") diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index ebdc3d4dd..64fc23883 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -66,6 +66,10 @@ function policy.policies() ["build.c++.modules"] = {description = "Enable C++ modules for C++ building.", type = "boolean"}, -- Enable std module ["build.c++.modules.std"] = {description = "Enable std modules.", default = true, type = "boolean"}, + -- Try to reuse compiled module bmi file if targets flags permit it + ["build.c++.modules.tryreuse"] = {description = "Try to reuse compiled module if possible.", default = true, type = "boolean"}, + -- Enable module taking defines acbount for bmi reuse discrimination + ["build.c++.modules.tryreuse.discriminate_on_defines"] = {description = "Enable defines module reuse discrimination.", default = false, type = "boolean"}, -- Force C++ modules fallback dependency scanner for clang ["build.c++.clang.fallbackscanner"] = {description = "Force clang fallback module dependency scanner.", default = false, type = "boolean"}, -- Force C++ modules fallback dependency scanner for msvc diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 936f90414..23515e988 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -33,7 +33,6 @@ import("dependency_scanner") -- build target modules function _build_modules(target, sourcebatch, modules, opt) local objectfiles = sourcebatch.objectfiles - _builder(target).populate_module_map(target, modules) -- build modules for _, objectfile in ipairs(objectfiles) do @@ -81,16 +80,79 @@ function _build_headerunits(target, headerunits, opt) end end +-- check if flags are compatible for module reuse +function _are_flags_compatible(target, other, cppfile) + local compinst1 = target:compiler("cxx") + local flags1 = compinst1:compflags({sourcefile = cppfile, target = target}) + + local compinst2 = other:compiler("cxx") + local flags2 = compinst2:compflags({sourcefile = cppfile, target = other}) + + -- strip unrelevent flags + flags1 = compiler_support.strip_flags(target, flags1) + flags2 = compiler_support.strip_flags(target, flags2) + + if #flags1 ~= #flags2 then + return false + end + + table.sort(flags1) + table.sort(flags2) + + for i = 1,#flags1 do + if flags1[i] ~= flags2[i] then + return false + end + end + + return true +end + +-- try to reuse modules from other target +function _try_reuse_modules(target, modules) + for _, module in pairs(modules) do + local name, provide, cppfile = compiler_support.get_provided_module(module) + if not provide then + goto CONTINUE + end + + cppfile = cppfile or module.cppfile + + local fileconfig = target:fileconfig(cppfile) + local public = fileconfig and (fileconfig.public or fileconfig.external) + if not public then + goto CONTINUE + end + + for _, dep in ipairs(target:orderdeps()) do + if not _are_flags_compatible(target, dep, cppfile) then + goto NEXT + end + local mapped = get_from_target_mapper(dep, name) + if mapped then + compiler_support.memcache():set2(target:name() .. name, "reuse", true) + add_module_to_target_mapper(target, mapped.name, mapped.sourcefile, mapped.bmi, table.join(mapped.opt or {}, {target = dep})) + break + end + ::NEXT:: + end + + ::CONTINUE:: + end + return modules +end + -- should we build this module or headerunit ? function should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt - local requires = opt.requires + local requires = opt and opt.requires if requires then for required, _ in table.orderpairs(requires) do local m = get_from_target_mapper(target, required) if m then - local rebuild = compiler_support.memcache():get2("should_build_in" .. target:name(), m.key) + local rebuild = (m.opt and m.opt.target) and compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + or compiler_support.memcache():get2("should_build_in_" .. target:name(), m.key) if rebuild then return true end @@ -98,6 +160,14 @@ function should_build(target, sourcefile, bmifile, opt) end end + -- reused + if opt and opt.name then + local m = get_from_target_mapper(target, opt.name) + if m and m.opt and m.opt.target then + return compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + end + end + -- or rebuild it if the file changed local objectfile = opt.objectfile local dryrun = option.get("dry-run") @@ -175,7 +245,7 @@ function _builder(target) end function mark_build(target, name) - compiler_support.memcache():set2("should_build_in" .. target:name(), name, true) + compiler_support.memcache():set2("should_build_in_" .. target:name(), name, true) end -- build batchjobs for modules @@ -189,6 +259,11 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op opt.rootjob = batchjobs:group_leave() or opt.rootjob batchjobs:group_enter(target:name() .. "/build_modules", {rootjob = opt.rootjob}) + batchjobs:addjob(target:name() .. "_populate_module_map", function(_, _) + _try_reuse_modules(target, modules) + _builder(target).populate_module_map(target, modules) + end, {rootjob = opt.rootjob}) + local modulesjobs = {} _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(deps, module, name, objectfile, cppfile) @@ -208,6 +283,9 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op local depmtime = 0 opt.progress = opt.progress or 0 + _try_reuse_modules(target, modules) + _builder(target).populate_module_map(target, modules) + -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(_, module, _, objectfile, cppfile) @@ -352,7 +430,9 @@ end -- add a module to target mapper function add_module_to_target_mapper(target, name, sourcefile, bmifile, opt) local mapper = get_target_module_mapper(target) - mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} + if not mapper[name] then + mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} + end flush_target_module_mapper_keys(target) end diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 0e5f0b5bd..05835b0e1 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -30,34 +30,38 @@ import("core.project.depend") import("compiler_support") import(".builder", {inherit = true}) --- get flags for building a module -function _make_modulebuildflags(target, provide, bmifile, opt) - +function _compile_one_step(target, bmifile, sourcefile, objectfile, opt) -- get flags local module_outputflag = compiler_support.get_moduleoutputflag(target) - - local flags - local precompile = false - if module_outputflag and provide and opt.build_objectfile then -- one step compilation of named module, clang >= 16 - flags = {{"-x", "c++-module", module_outputflag .. bmifile}} - elseif provide then -- two step compilation of named module - precompile = true - flags = {{"-x", "c++-module", "--precompile"}} - if opt.build_objectfile then - table.insert(flags, {}) + if module_outputflag then + local flags = table.join({"-x", "c++-module", module_outputflag .. bmifile}, opt.std and {"-Wno-include-angled-in-module-purview", "-Wno-reserved-module-identifier"} or {}) + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, flags, sourcefile, objectfile) + else + _compile(target, flags, sourcefile, objectfile) end - else -- internal module, no bmi needed - flags = {{"-x", "c++"}} + else + _compile_bmi_step(target, bmifile, sourcefile, opt) + _compile_objectfile_step(target, bmifile, sourcefile, objectfile, opt) end +end - if opt.name == "std" or opt.name == "std.compat" then - table.join2(flags[1], {"-Wno-include-angled-in-module-purview", "-Wno-reserved-module-identifier"}) - if flags[2] then - table.join2(flags[2], {"-Wno-include-angled-in-module-purview", "-Wno-reserved-module-identifier"}) - end +function _compile_bmi_step(target, bmifile, sourcefile, opt) + local flags = table.join({"-x", "c++-module", "--precompile"}, opt.std and {"-Wno-include-angled-in-module-purview", "-Wno-reserved-module-identifier"} or {}) + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, flags, sourcefile, bmifile) + else + _compile(target, flags, sourcefile, bmifile) end +end - return precompile, table.unpack(flags) +function _compile_objectfile_step(target, bmifile, sourcefile, objectfile, opt) + _compile(target, {}, sourcefile, objectfile, {bmifile = bmifile}) + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, {}, sourcefile, objectfile, {bmifile = bmifile}) + else + _compile(target, {}, sourcefile, objectfile, {bmifile = bmifile}) + end end -- get flags for building a headerunit @@ -198,16 +202,24 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) return { name = job_name, - deps = deps, + deps = table.join(target:name() .. "_populate_module_map", deps), sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end + end local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) local build if provide or compiler_support.has_module_extension(opt.cppfile) then - build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) -- needed to detect rebuild of dependencies if provide and build then @@ -222,7 +234,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) -- for cpp file we need to check after appendings the flags if build == nil then - build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) end local dependfile = target:dependfile(bmifile or opt.objectfile) @@ -233,8 +245,6 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then local objectdir = path.directory(opt.objectfile) if not os.isdir(objectdir) then @@ -242,17 +252,26 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local fileconfig = target:fileconfig(opt.cppfile) - local public = fileconfig and fileconfig.public - local external = fileconfig and fileconfig.external - local build_objectfile = target:kind() == "binary" or (not public and not external) - - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) - - _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - - if second_step then - _compile(target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local bmifile = mapped_bmi or bmifile + if target:is_binary() then + if mapped_bmi then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + _compile_objectfile_step(target, bmifile, opt.cppfile, opt.objectfile) + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, {std = (name == "std" or name == "std.compat")}) + end + else + if not public and not external then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, {std = (name == "std" or name == "std.compat")}) + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + _compile_bmi_step(target, bmifile, opt.cppfile, {std = (name == "std" or name == "std.compat")}) + end end else os.tryrm(opt.objectfile) -- force rebuild for .cpp files @@ -271,9 +290,18 @@ function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end + end + local build if provide or compiler_support.has_module_extension(opt.cppfile) then - build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) -- needed to detect rebuild of dependencies if provide and build then @@ -288,26 +316,34 @@ function make_module_buildcmds(target, batchcmds, opt) -- for cpp file we need to check after appendings the flags if build == nil then - build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) end - local build_objectfile = target:kind() == "binary" if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) local fileconfig = target:fileconfig(opt.cppfile) local public = fileconfig and fileconfig.public local external = fileconfig and fileconfig.external - local build_objectfile = target:kind() == "binary" or (not public and not external) - - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name}) - _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - - if second_step then - _batchcmds_compile(batchcmds, target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + local bmifile = mapped_bmi or bmifile + if target:is_binary() then + if mapped_bmi then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + _compile_objectfile_step(target, bmifile, opt.cppfile, opt.objectfile, {batchcmds = batchcmds}) + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, {std = (name == "std" or name == "std.compat"), batchcmds = batchcmds}) + end + else + if not public and not external then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, {std = (name == "std" or name == "std.compat"), batchcmds = batchcmds}) + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + _compile_bmi_step(target, bmifile, opt.cppfile, {std = (name == "std" or name == "std.compat"), batchcmds = batchcmds}) + end end else batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 9f581cdca..7d25c5fcc 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -107,6 +107,43 @@ function load(target) end end +-- strip flags that doesn't affect bmi generation +function strip_flags(target, flags) + -- speculative list as there is no resource that list flags that prevent reusability, this list will likely be improve over time + -- @see https://clang.llvm.org/docs/StandardCPlusPlusModules.html#consistency-requirement + local strippable_flags = { + "-I", + "-isystem", + "-g", + "-O", + "-W", + "-w", + "-cxx-isystem", + "-Q", + } + if not target:policy("build.c++.modules.tryreuse.discriminate_on_defines") then + table.join2(strippable_flags, {"-D", "-U"}) + end + local output = {} + local last_flag_I = false + for _, flag in ipairs(flags) do + local strip = false + + for _, _flag in ipairs(strippable_flags) do + if flag:startswith(_flag) or last_flag_I then + last_flag_I = _flag == "-I" + strip = true + break + end + end + + if not strip then + table.insert(output, flag) + end + end + return output +end + -- provide toolchain include directories for stl headerunit when p1689 is not supported function toolchain_includedirs(target) local includedirs = _g.includedirs diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua index d11e833fd..9d3d4fadf 100644 --- a/xmake/rules/c++/modules/modules_support/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua @@ -49,6 +49,11 @@ function load(target) _compiler_support(target).load(target) end +-- strip flags not relevent for module reuse +function strip_flags(target, flags) + return _compiler_support(target).strip_flags(target, flags) +end + -- patch sourcebatch function patch_sourcebatch(target, sourcebatch) sourcebatch.sourcekind = "cxx" diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index c4c9871e2..11eaf24c1 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -30,11 +30,6 @@ import("core.project.depend") import("compiler_support") import(".builder", {inherit = true}) --- get flags for building a module -function _make_modulebuildflags(target, opt) - return {"-x", "c++", "-c"} -end - -- get flags for building a headerunit function _make_headerunitflags(target, headerunit, headerunit_mapper) local module_headerflag = compiler_support.get_moduleheaderflag(target) @@ -99,7 +94,7 @@ end function _get_maplines(target, module) local maplines = {} - local m_name, m, cppfile = compiler_support.get_provided_module(module) + local m_name, m, _ = compiler_support.get_provided_module(module) if m then table.insert(maplines, m_name .. " " .. compiler_support.get_bmi_path(m.bmi)) end @@ -140,10 +135,10 @@ end -- /usr/include/c++/11/iostream build/.gens/stl_headerunit/linux/x86_64/release/stlmodules/cache/iostream.gcm -- hello build/.gens/stl_headerunit/linux/x86_64/release/rules/modules/cache/hello.gcm -- -function _generate_modulemapper_file(target, module) +function _generate_modulemapper_file(target, module, cppfile) local maplines = _get_maplines(target, module) - local path = os.tmpfile() - local mapper_file = io.open(path, "wb") + local mapper_path = path.join(os.tmpdir(), target:name():replace(" ", "_"), name or cppfile:replace(" ", "_")) + local mapper_file = io.open(mapper_path, "wb") mapper_file:write("root " .. os.projectdir():replace("\\", "/")) mapper_file:write("\n") for _, mapline in ipairs(maplines) do @@ -151,7 +146,7 @@ function _generate_modulemapper_file(target, module) mapper_file:write("\n") end mapper_file:close() - return path + return mapper_path end -- populate module map @@ -188,27 +183,35 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) return { name = job_name, - deps = deps, + deps = table.join(target:name() .. "_populate_module_map", deps), sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end + end local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) - local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) - - -- needed to detect rebuild of dependencies - if provide and build then - mark_build(target, name) - end - -- generate and append module mapper file local module_mapper if provide or opt.module.requires then - module_mapper = _generate_modulemapper_file(target, opt.module) + module_mapper = _generate_modulemapper_file(target, opt.module, opt.cppfile) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end + local build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} @@ -217,13 +220,35 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local bmifile = mapped_bmi or bmifile + local flags = {"-x", "c++"} + local sourcefile + if target:is_binary() then + if mapped_bmi then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = bmifile + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = opt.cppfile + end + else + if not public and not external then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = opt.cppfile + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + local module_onlyflag = compiler_support.get_moduleonlyflag(target) + table.insert(flags, module_onlyflag) + sourcefile = opt.cppfile + end + end if option.get("diagnosis") then print("mapper file --------\n%s--------", io.readfile(module_mapper)) end - - local flags = _make_modulebuildflags(target, opt) - _compile(target, flags, opt.cppfile, opt.objectfile) + _compile(target, flags, sourcefile, opt.objectfile) os.tryrm(module_mapper) else os.tryrm(opt.objectfile) -- force rebuild for .cpp files @@ -242,29 +267,63 @@ function make_module_buildcmds(target, batchcmds, opt) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) local module_mapperflag = compiler_support.get_modulemapperflag(target) - local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) - - -- needed to detect rebuild of dependencies - if provide and build then - mark_build(target, name) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end end -- generate and append module mapper file local module_mapper if provide or opt.module.requires then - module_mapper = _generate_modulemapper_file(target, opt.module) + module_mapper = _generate_modulemapper_file(target, opt.module, opt.cppfile) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end + local build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + batchcmds:mkdir(path.directory(opt.objectfile)) + local fileconfig = target:fileconfig(opt.cppfile) + local public = fileconfig and fileconfig.public + local external = fileconfig and fileconfig.external + local bmifile = mapped_bmi or bmifile + local flags = {"-x", "c++"} + local sourcefile + if target:is_binary() then + if mapped_bmi then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = bmifile + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = opt.cppfile + end + else + if not public and not external then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + sourcefile = opt.cppfile + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + local module_onlyflag = compiler_support.get_moduleonlyflag(target) + table.insert(flags, module_onlyflag) + sourcefile = opt.cppfile + end + end if option.get("diagnosis") then batchcmds:print("mapper file: %s", io.readfile(module_mapper)) end - batchcmds:mkdir(path.directory(opt.objectfile)) - _batchcmds_compile(batchcmds, target, _make_modulebuildflags(target, {batchcmds = true, sourcefile = opt.cppfile}), opt.cppfile, opt.objectfile) + _batchcmds_compile(batchcmds, target, flags, sourcefile, opt.objectfile) + batchcmds:rm(module_mapper) else batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end diff --git a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua index c365a107a..95067567b 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua @@ -65,6 +65,41 @@ function load(target) end end +-- strip flags that doesn't affect bmi generation +function strip_flags(target, flags) + -- speculative list as there is no resource that list flags that prevent reusability, this list will likely be improve over time + local strippable_flags = { + "-I", + "-isystem", + "-g", + "-O", + "-W", + "-w", + "-cxx-isystem", + "-Q", + } + if not target:policy("build.c++.modules.tryreuse.discriminate_on_defines") then + table.join2(strippable_flags, {"-D", "-U"}) + end + local output = {} + local last_flag_I = false + for _, flag in ipairs(flags) do + local strip = false + + for _, _flag in ipairs(strippable_flags) do + if flag:startswith(_flag) or last_flag_I then + last_flag_I = _flag == "-I" + strip = true + break + end + end + if not strip then + table.insert(output, flag) + end + end + return output +end + -- provide toolchain include directories for stl headerunit when p1689 is not supported function toolchain_includedirs(target) local includedirs = _g.includedirs diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 3fc86b369..9fce72e70 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -47,6 +47,56 @@ function _make_modulebuildflags(target, provide, bmifile, opt) end return flags end +function _compile_one_step(target, bmifile, sourcefile, objectfile, provide, opt) + local ifcoutputflag = compiler_support.get_ifcoutputflag(target) + local interfaceflag = compiler_support.get_interfaceflag(target) + local internalpartitionflag = compiler_support.get_internalpartitionflag(target) + -- get flags + local flags = {"-TP"} + if provide then + table.join2(flags, ifcoutputflag, path(bmifile), provide.interface and interfaceflag or internalpartitionflag) + end + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, flags, sourcefile, objectfile) + else + _compile(target, flags, sourcefile, objectfile) + end +end + +function _compile_bmi_step(target, bmifile, sourcefile, objectfile, provide, opt) + local ifcoutputflag = compiler_support.get_ifcoutputflag(target) + local interfaceflag = compiler_support.get_interfaceflag(target) + local ifconlyflag = compiler_support.get_ifconlyflag(target) + + if not ifconlyflag then + _compile_one_step(target, bmifile, sourcefile, objectfile, provide, opt) + else + local flags = {"-TP", ifcoutputflag, path(bmifile), interfaceflag, ifconlyflag} + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, flags, sourcefile, bmifile) + else + _compile(target, flags, sourcefile, bmifile) + end + end +end + +function _compile_objectfile_step(target, bmifile, sourcefile, objectfile, provide, opt) + local ifconlyflag = compiler_support.get_ifconlyflag(target) + local interfaceflag = compiler_support.get_interfaceflag(target) + local internalpartitionflag = compiler_support.get_internalpartitionflag(target) + + local flags = {"-TP", (provide and provide.interface) and interfaceflag or internalpartitionflag} + if not ifconlyflag then + _compile_one_step(target, bmifile, sourcefile, objectfile, provide, opt) + else + if opt and opt.batchcmds then + _batchcmds_compile(opt.batchcmds, target, flags, sourcefile, objectfile) + else + _compile(target, flags, sourcefile, objectfile) + end + end +end + -- get flags for building a headerunit function _make_headerunitflags(target, headerunit, bmifile) @@ -215,13 +265,22 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) return { name = job_name, - deps = deps, + deps = table.join(target:name() .. "_populate_module_map", deps), sourcefile = opt.cppfile, job = batchjobs:newjob(name or opt.cppfile, function(index, total) local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end + end + local build if provide or compiler_support.has_module_extension(opt.cppfile) then build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) @@ -250,8 +309,6 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then local objectdir = path.directory(opt.objectfile) if not os.isdir(objectdir) then @@ -262,10 +319,24 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local fileconfig = target:fileconfig(opt.cppfile) local public = fileconfig and fileconfig.public local external = fileconfig and fileconfig.external - local build_objectfile = target:kind() == "binary" or (not public and not external) - local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile}) - - _compile(target, flags, opt.cppfile, opt.objectfile) + local bmifile = mapped_bmi or bmifile + if target:is_binary() then + if mapped_bmi then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + _compile_objectfile_step(target, bmifile, opt.cppfile, opt.objectfile, provide) + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, provide) + end + else + if not public and not external then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, provide) + else + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + _compile_bmi_step(target, bmifile, opt.cppfile, opt.objectfile, provide) + end + end else os.tryrm(opt.objectfile) -- force rebuild for .cpp files end @@ -283,6 +354,15 @@ function make_module_buildcmds(target, batchcmds, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) + local mapped_bmi + if provide and compiler_support.memcache():get2(target:name() .. name, "reuse") then + if not target:is_binary() then + return + else + mapped_bmi = get_from_target_mapper(target, name).bmi + end + end + local build if provide or compiler_support.has_module_extension(opt.cppfile) then build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) @@ -306,15 +386,29 @@ function make_module_buildcmds(target, batchcmds, opt) if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then - batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) local fileconfig = target:fileconfig(opt.cppfile) local public = fileconfig and fileconfig.public local external = fileconfig and fileconfig.external - local build_objectfile = target:kind() == "binary" or (not public and not external) - local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile}) - _batchcmds_compile(batchcmds, target, flags, opt.cppfile, opt.objectfile) + local bmifile = mapped_bmi or bmifile + if target:is_binary() then + if mapped_bmi then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.objectfile.$(mode) %s", target:name(), name or opt.cppfile) + _compile_objectfile_step(target, bmifile, opt.cppfile, opt.objectfile, provide, {batchcmds = batchcmds}) + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, provide, {batchcmds = batchcmds}) + end + else + if not public and not external then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + _compile_one_step(target, bmifile, opt.cppfile, opt.objectfile, provide {batchcmds = batchcmds}) + else + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.bmi.$(mode) %s", target:name(), name or opt.cppfile) + _compile_bmi_step(target, bmifile, opt.cppfile, provide, {batchcmds = batchcmds}) + end + end else batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end diff --git a/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua b/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua index e65effa11..69f677706 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua @@ -56,6 +56,64 @@ function load(target) end end +-- strip flags that doesn't affect bmi generation +function strip_flags(target, flags) + -- speculative list as there is no resource that list flags that prevent reusability, this list will likely be improve over time + -- @see https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=msvc-170 + local strippable_flags = { + "I", + "TP", + "errorReport", + "W", + "w", + "sourceDependencies", + "scanDependencies", + "reference", + "PD", + "nologo", + "MP", + "internalPartition", + "interface", + "ifcOutput", + "help", + "headerUnit", + "headerName", + "Fp", + "Fo", + "Fm", + "Fe", + "Fd", + "FC", + "exportHeader", + "EP", + "E", + "doc", + "diagnostics", + "cgthreads", + "C", + "analyze", + "?", + } + if not target:policy("build.c++.modules.tryreuse.discriminate_on_defines") then + table.join2(strippable_flags, {"D", "U"}) + end + local output = {} + for _, flag in ipairs(flags) do + local strip = false + for _, _flag in ipairs(strippable_flags) do + if flag:startswith("cl::-" .. _flag) or flag:startswith("cl::/" .. _flag) or + flag:startswith("-" .. _flag) or flag:startswith("/" .. _flag) then + strip = true + break + end + end + if not strip then + table.insert(output, flag) + end + end + return output +end + -- provide toolchain include dir for stl headerunit when p1689 is not supported function toolchain_includedirs(target) for _, toolchain_inst in ipairs(target:toolchains()) do -- cgit v1.3.1 From be329f008903ce4989bdd0de7cea6f48d54b2d63 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 14 Feb 2024 13:33:55 +0100 Subject: cleanup --- xmake/rules/c++/modules/modules_support/builder.lua | 2 +- xmake/rules/c++/modules/modules_support/clang/compiler_support.lua | 2 -- xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 23515e988..a33f69261 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -99,7 +99,7 @@ function _are_flags_compatible(target, other, cppfile) table.sort(flags1) table.sort(flags2) - for i = 1,#flags1 do + for i = 1, #flags1 do if flags1[i] ~= flags2[i] then return false end diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 7d25c5fcc..49e01db90 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -128,7 +128,6 @@ function strip_flags(target, flags) local last_flag_I = false for _, flag in ipairs(flags) do local strip = false - for _, _flag in ipairs(strippable_flags) do if flag:startswith(_flag) or last_flag_I then last_flag_I = _flag == "-I" @@ -136,7 +135,6 @@ function strip_flags(target, flags) break end end - if not strip then table.insert(output, flag) end diff --git a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua index 95067567b..2253c9866 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua @@ -85,7 +85,6 @@ function strip_flags(target, flags) local last_flag_I = false for _, flag in ipairs(flags) do local strip = false - for _, _flag in ipairs(strippable_flags) do if flag:startswith(_flag) or last_flag_I then last_flag_I = _flag == "-I" -- cgit v1.3.1 From b92d9b0ed1c41a85c37278d81662c6390913fc02 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 18 Feb 2024 15:32:51 +0800 Subject: format code --- xmake/rules/c++/modules/modules_support/builder.lua | 21 +++++++++------------ .../c++/modules/modules_support/gcc/builder.lua | 5 +++-- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index a33f69261..77fe019cc 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -33,12 +33,10 @@ import("dependency_scanner") -- build target modules function _build_modules(target, sourcebatch, modules, opt) local objectfiles = sourcebatch.objectfiles - - -- build modules for _, objectfile in ipairs(objectfiles) do local module = modules[objectfile] if not module then - goto CONTINUE + goto continue end local name, _, cppfile = compiler_support.get_provided_module(module) @@ -51,7 +49,7 @@ function _build_modules(target, sourcebatch, modules, opt) opt.build_module(deps, module, name, objectfile, cppfile) - ::CONTINUE:: + ::continue:: end end @@ -113,7 +111,7 @@ function _try_reuse_modules(target, modules) for _, module in pairs(modules) do local name, provide, cppfile = compiler_support.get_provided_module(module) if not provide then - goto CONTINUE + goto continue end cppfile = cppfile or module.cppfile @@ -121,12 +119,12 @@ function _try_reuse_modules(target, modules) local fileconfig = target:fileconfig(cppfile) local public = fileconfig and (fileconfig.public or fileconfig.external) if not public then - goto CONTINUE + goto continue end for _, dep in ipairs(target:orderdeps()) do if not _are_flags_compatible(target, dep, cppfile) then - goto NEXT + goto nextdep end local mapped = get_from_target_mapper(dep, name) if mapped then @@ -134,10 +132,10 @@ function _try_reuse_modules(target, modules) add_module_to_target_mapper(target, mapped.name, mapped.sourcefile, mapped.bmi, table.join(mapped.opt or {}, {target = dep})) break end - ::NEXT:: + ::nextdep:: end - ::CONTINUE:: + ::continue:: end return modules end @@ -255,7 +253,6 @@ end -- build modules for batchjobs function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - opt.rootjob = batchjobs:group_leave() or opt.rootjob batchjobs:group_enter(target:name() .. "/build_modules", {rootjob = opt.rootjob}) @@ -268,8 +265,8 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(deps, module, name, objectfile, cppfile) local job_name = name and target:name() .. name or cppfile - - modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {module = module, objectfile = objectfile, cppfile = cppfile}) + modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, + {module = module, objectfile = objectfile, cppfile = cppfile}) end })) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 76f3f28ec..cb5d3ef18 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -355,12 +355,13 @@ function make_headerunit_buildjobs(target, job_name, batchjobs, headerunit, bmif if opt.build then local headerunit_mapper = _generate_headerunit_modulemapper_file({name = path.normalize(headerunit.path), bmifile = bmifile}) - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.headerunit.$(mode) %s", target:name(), headerunit.name) if option.get("diagnosis") then print("mapper file:\n%s", io.readfile(headerunit_mapper)) end - _compile(target, _make_headerunitflags(target, headerunit, headerunit_mapper, opt), path.translate(path.filename(headerunit.name)), bmifile) + _compile(target, + _make_headerunitflags(target, headerunit, headerunit_mapper, opt), + path.translate(path.filename(headerunit.name)), bmifile) os.tryrm(headerunit_mapper) end -- cgit v1.3.1 From c3635e4b133a5f324419b4f7f5ebbdd2b53e56f8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 18 Feb 2024 15:54:23 +0800 Subject: fix incremental compilation for tests/ modules/package --- xmake/rules/c++/modules/modules_support/builder.lua | 2 -- xmake/rules/c++/modules/modules_support/gcc/builder.lua | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 77fe019cc..505ba07fb 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -178,11 +178,9 @@ function should_build(target, sourcefile, bmifile, opt) -- need build this object? local depvalues = {compinst:program(), compflags} local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 - if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then return true end - return false end diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index cb5d3ef18..173c12fe2 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -193,9 +193,6 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) - -- generate and append module mapper file local module_mapper if provide or opt.module.requires then @@ -210,6 +207,9 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) mark_build(target, name) end + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} -- cgit v1.3.1 From bc1a30db6041c2c14ca79ccf0aa35b2d550e64e5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 18 Feb 2024 17:08:22 +0800 Subject: improve should_build for modules --- .../rules/c++/modules/modules_support/builder.lua | 40 ++++++++++++++-------- .../c++/modules/modules_support/clang/builder.lua | 20 +++-------- .../c++/modules/modules_support/gcc/builder.lua | 15 ++------ .../c++/modules/modules_support/msvc/builder.lua | 20 +++-------- 4 files changed, 38 insertions(+), 57 deletions(-) (limited to 'xmake/rules/c++/modules/modules_support/builder.lua') diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 505ba07fb..523a421b0 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -142,9 +142,16 @@ end -- should we build this module or headerunit ? function should_build(target, sourcefile, bmifile, opt) + opt = opt or {} + local objectfile = opt.objectfile + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) + local dependfile = target:dependfile(bmifile or objectfile) + local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) + local depvalues = {compinst:program(), compflags} -- force rebuild a module if any of its module dependency is rebuilt - local requires = opt and opt.requires + local requires = opt.requires if requires then for required, _ in table.orderpairs(requires) do local m = get_from_target_mapper(target, required) @@ -152,34 +159,37 @@ function should_build(target, sourcefile, bmifile, opt) local rebuild = (m.opt and m.opt.target) and compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) or compiler_support.memcache():get2("should_build_in_" .. target:name(), m.key) if rebuild then - return true + dependinfo.files = {} + table.insert(dependinfo.files, sourcefile) + dependinfo.values = depvalues + return true, dependinfo end end end end -- reused - if opt and opt.name then + if opt.name then local m = get_from_target_mapper(target, opt.name) if m and m.opt and m.opt.target then - return compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + local rebuild = compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + if rebuild then + dependinfo.files = {} + table.insert(dependinfo.files, sourcefile) + dependinfo.values = depvalues + end + return rebuild, dependinfo end end - -- or rebuild it if the file changed - local objectfile = opt.objectfile - local dryrun = option.get("dry-run") - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) - - local dependfile = target:dependfile(bmifile or objectfile) - local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) - -- need build this object? - local depvalues = {compinst:program(), compflags} + local dryrun = option.get("dry-run") local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then - return true + dependinfo.files = {} + table.insert(dependinfo.files, sourcefile) + dependinfo.values = depvalues + return true, dependinfo end return false end diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 44787615b..6a912bed4 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -214,9 +214,10 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local build + local build, dependinfo + local dependfile = target:dependfile(bmifile or opt.objectfile) if provide or compiler_support.has_module_extension(opt.cppfile) then - build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + build, dependinfo = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) -- needed to detect rebuild of dependencies if provide and build then @@ -231,17 +232,9 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) -- for cpp file we need to check after appendings the flags if build == nil then - build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + build, dependinfo = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) end - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) - - local dependfile = target:dependfile(bmifile or opt.objectfile) - local dependinfo = depend.load(dependfile) or {} - dependinfo.files = {} - local depvalues = {compinst:program(), compflags} - if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then @@ -276,11 +269,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) else os.tryrm(opt.objectfile) -- force rebuild for .cpp files end + depend.save(dependinfo, dependfile) end - - table.insert(dependinfo.files, opt.cppfile) - dependinfo.values = depvalues - depend.save(dependinfo, dependfile) end)} end diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 173c12fe2..9b8ed1212 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -200,21 +200,14 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end - local build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + local dependfile = target:dependfile(bmifile or opt.objectfile) + local build, dependinfo = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) -- needed to detect rebuild of dependencies if provide and build then mark_build(target, name) end - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) - - local dependfile = target:dependfile(bmifile or opt.objectfile) - local dependinfo = depend.load(dependfile) or {} - dependinfo.files = {} - local depvalues = {compinst:program(), compflags} - if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then @@ -251,10 +244,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) else os.tryrm(opt.objectfile) -- force rebuild for .cpp files end + depend.save(dependinfo, dependfile) end - table.insert(dependinfo.files, opt.cppfile) - dependinfo.values = depvalues - depend.save(dependinfo, dependfile) end)} end diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 996b9984c..5bb9fc4d8 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -278,9 +278,10 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end end - local build + local build, dependinfo + local dependfile = target:dependfile(bmifile or opt.objectfile) if provide or compiler_support.has_module_extension(opt.cppfile) then - build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + build, dependinfo = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) -- needed to detect rebuild of dependencies if provide and build then @@ -295,17 +296,9 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) -- for cpp file we need to check after appendings the flags if build == nil then - build = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) + build, dependinfo = should_build(target, opt.cppfile, bmifile, {name = name, objectfile = opt.objectfile, requires = opt.module.requires}) end - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) - - local dependfile = target:dependfile(bmifile or opt.objectfile) - local dependinfo = depend.load(dependfile) or {} - dependinfo.files = {} - local depvalues = {compinst:program(), compflags} - if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then @@ -340,11 +333,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) else os.tryrm(opt.objectfile) -- force rebuild for .cpp files end + depend.save(dependinfo, dependfile) end - - table.insert(dependinfo.files, opt.cppfile) - dependinfo.values = depvalues - depend.save(dependinfo, dependfile) end)} end -- cgit v1.3.1