diff options
| author | ruki <[email protected]> | 2026-08-07 00:09:35 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2026-08-07 00:09:35 +0800 |
| commit | c3c015e48dc1e8808e95e977d4fcd62cc3ba89b2 (patch) | |
| tree | 838131b358b50ed8569ba42945c6b866bec5e394 | |
| parent | 53c06b72cc8b1521aae266543aee634c917a030f (diff) | |
fix build.c++.modules.tryreuse deps orders
6 files changed, 58 insertions, 5 deletions
diff --git a/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.cpp b/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.cpp new file mode 100644 index 000000000..5b9d1194e --- /dev/null +++ b/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.cpp @@ -0,0 +1,5 @@ +module foo; + +auto my_sum(int a, int b) -> int { + return a + b; +} diff --git a/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.mpp b/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.mpp new file mode 100644 index 000000000..4c9a649ca --- /dev/null +++ b/tests/projects/c++/modules/stdmodules_deps_ordering/src/foo.mpp @@ -0,0 +1,3 @@ +export module foo; + +export auto my_sum(int a, int b) -> int; diff --git a/tests/projects/c++/modules/stdmodules_deps_ordering/src/main.cpp b/tests/projects/c++/modules/stdmodules_deps_ordering/src/main.cpp new file mode 100644 index 000000000..1f87ceb59 --- /dev/null +++ b/tests/projects/c++/modules/stdmodules_deps_ordering/src/main.cpp @@ -0,0 +1,8 @@ +import foo; + +import std; + +int main() { + std::cout << my_sum(1, 2) << std::endl; + return 0; +} diff --git a/tests/projects/c++/modules/stdmodules_deps_ordering/test.lua b/tests/projects/c++/modules/stdmodules_deps_ordering/test.lua new file mode 100644 index 000000000..e77adc4ae --- /dev/null +++ b/tests/projects/c++/modules/stdmodules_deps_ordering/test.lua @@ -0,0 +1 @@ +inherit(".test_stdmodules") diff --git a/tests/projects/c++/modules/stdmodules_deps_ordering/xmake.lua b/tests/projects/c++/modules/stdmodules_deps_ordering/xmake.lua new file mode 100644 index 000000000..09c3f6a94 --- /dev/null +++ b/tests/projects/c++/modules/stdmodules_deps_ordering/xmake.lua @@ -0,0 +1,19 @@ +add_rules("mode.debug", "mode.release") +set_languages("c++latest") + +-- test that a plain c++ file is ordered after all the bmis it reuses from its deps, +-- not only after the last one +-- +-- @note foo must not import std, otherwise its bmi and the std bmi +-- would not be built by two distinct jobs of the foo target +-- +-- @see https://github.com/xmake-io/xmake/issues/7690 +target("foo") + set_kind("static") + add_files("src/foo.cpp") + add_files("src/foo.mpp", {public = true}) + +target("main") + set_kind("binary") + add_deps("foo") + add_files("src/main.cpp") diff --git a/xmake/rules/c++/modules/builder.lua b/xmake/rules/c++/modules/builder.lua index 6d82cca0b..d0863ad98 100644 --- a/xmake/rules/c++/modules/builder.lua +++ b/xmake/rules/c++/modules/builder.lua @@ -85,6 +85,23 @@ function _get_buildfilejob_for(target, sourcefile, opt) return _get_module_buildfilejob_for(target, sourcefile, opt.moduletype) end +-- merge jobdeps, we cannot use table.join2 directly, +-- because it will override the previous deps with the same job name +-- +-- e.g. a consumer job may depend on several reused bmi jobs from the same dep target +-- @see https://github.com/xmake-io/xmake/issues/7690 +function _merge_jobdeps(jobdeps, deps) + for jobname, depnames in pairs(deps) do + local orderdeps = jobdeps[jobname] + if orderdeps then + table.join2(orderdeps, depnames) + else + jobdeps[jobname] = table.wrap(depnames) + end + end + return jobdeps +end + function _get_jobdeps(target, module, jobgraph, buildfilejob) local memcache = support.memcache() @@ -236,11 +253,11 @@ function build_modules_for_jobgraph(target, jobgraph, built_modules) else if not support.is_bmionly(target, sourcefile) then local buildfilejob = _get_module_buildfilejob_for(target, sourcefile, "objectfile") - table.join2(jobdeps, _get_jobdeps(target, module, jobgraph, buildfilejob)) + _merge_jobdeps(jobdeps, _get_jobdeps(target, module, jobgraph, buildfilejob)) table.insert(buildfilejobs, buildfilejob) local objbuildfilejob = target:fullname() .. "/obj/" .. sourcefile if jobgraph:has(objbuildfilejob) then - jobdeps[objbuildfilejob] = {buildfilejob} + _merge_jobdeps(jobdeps, {[objbuildfilejob] = {buildfilejob}}) end end end @@ -262,19 +279,19 @@ function build_modules_for_jobgraph(target, jobgraph, built_modules) jobopt.objectfile = not has_two_phase_compilation_support and not bmionly builder.make_module_job(target, module, jobopt) end) - table.join2(jobdeps, _get_jobdeps(target, module, jobgraph, buildfilejob)) + _merge_jobdeps(jobdeps, _get_jobdeps(target, module, jobgraph, buildfilejob)) -- if two phase compilation supported set jobdeps for objectfile job if has_two_phase_compilation_support and not bmionly then local objbuildfilejob = _get_module_buildfilejob_for(target, sourcefile, "objectfile") - jobdeps[objbuildfilejob] = {buildfilejob} + _merge_jobdeps(jobdeps, {[objbuildfilejob] = {buildfilejob}}) end end end) -- insert saved jobdeps for _, buildfilejob in ipairs(buildfilejobs) do - table.join2(jobdeps, _get_saved_jobdeps_for(jobgraph, buildfilejob)) + _merge_jobdeps(jobdeps, _get_saved_jobdeps_for(jobgraph, buildfilejob)) end -- apply jobdeps |
