From 54be8114524841180f4e3741f23668c149b0553e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 24 Jan 2026 21:41:02 +0800 Subject: add multiple targets with pch --- .../src/common.h | 3 ++ .../src/consumer.cpp | 11 +++++++ .../src/lib1.cpp | 7 ++++ .../src/lib1_pch.h | 3 ++ .../src/lib2.cpp | 12 +++++++ .../src/lib2_pch.h | 3 ++ .../src/main.cpp | 19 +++++++++++ .../src/simple.cpp | 8 +++++ .../src/tool.cpp | 15 +++++++++ .../src/tool_pch.h | 3 ++ .../precompiled_header_multiple_targets/test.lua | 3 ++ .../precompiled_header_multiple_targets/xmake.lua | 38 ++++++++++++++++++++++ 12 files changed, 125 insertions(+) create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/common.h create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/consumer.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/lib1.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/lib1_pch.h create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/lib2.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/lib2_pch.h create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/main.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/simple.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/tool.cpp create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/src/tool_pch.h create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/test.lua create mode 100644 tests/projects/c++/precompiled_header_multiple_targets/xmake.lua diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/common.h b/tests/projects/c++/precompiled_header_multiple_targets/src/common.h new file mode 100644 index 000000000..728d5329d --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/common.h @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/consumer.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/consumer.cpp new file mode 100644 index 000000000..dd262d3ea --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/consumer.cpp @@ -0,0 +1,11 @@ +#include + +// Declare the function from lib1 +int lib1_function(); + +int main() { + std::cout << "Consumer program without PCH" << std::endl; + int result = lib1_function(); + std::cout << "lib1 result: " << result << std::endl; + return 0; +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/lib1.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/lib1.cpp new file mode 100644 index 000000000..10e464e26 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/lib1.cpp @@ -0,0 +1,7 @@ +#include "lib1_pch.h" + +int lib1_function() { + std::vector numbers = {1, 2, 3, 4, 5}; + int sum = std::accumulate(numbers.begin(), numbers.end(), 0); + return sum; +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/lib1_pch.h b/tests/projects/c++/precompiled_header_multiple_targets/src/lib1_pch.h new file mode 100644 index 000000000..171ea49d2 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/lib1_pch.h @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/lib2.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/lib2.cpp new file mode 100644 index 000000000..b9ec0230d --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/lib2.cpp @@ -0,0 +1,12 @@ +#include "lib2_pch.h" + +int lib2_function() { + std::map data = {{1, "one"}, {2, "two"}, {3, "three"}}; + std::set keys; + + for (const auto& pair : data) { + keys.insert(pair.first); + } + + return keys.size(); +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/lib2_pch.h b/tests/projects/c++/precompiled_header_multiple_targets/src/lib2_pch.h new file mode 100644 index 000000000..997e3abeb --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/lib2_pch.h @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/main.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/main.cpp new file mode 100644 index 000000000..766b9e817 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/main.cpp @@ -0,0 +1,19 @@ +#include "common.h" + +int lib1_function(); +int lib2_function(); + +int main() { + std::cout << "Main program started" << std::endl; + + int result1 = lib1_function(); + int result2 = lib2_function(); + + std::cout << "lib1 result: " << result1 << std::endl; + std::cout << "lib2 result: " << result2 << std::endl; + + std::vector vec = {result1, result2}; + std::cout << "Combined result: " << vec[0] + vec[1] << std::endl; + + return 0; +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/simple.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/simple.cpp new file mode 100644 index 000000000..a5849d4d9 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/simple.cpp @@ -0,0 +1,8 @@ +#include +#include + +int main() { + std::string message = "Simple program without PCH"; + std::cout << message << std::endl; + return 0; +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/tool.cpp b/tests/projects/c++/precompiled_header_multiple_targets/src/tool.cpp new file mode 100644 index 000000000..65c70e5f1 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/tool.cpp @@ -0,0 +1,15 @@ +#include "tool_pch.h" + +int main() { + std::stringstream ss; + ss << "Tool program output"; + + std::ofstream outfile("tool_output.txt"); + if (outfile.is_open()) { + outfile << ss.str() << std::endl; + outfile.close(); + } + + std::cout << "Tool completed successfully" << std::endl; + return 0; +} diff --git a/tests/projects/c++/precompiled_header_multiple_targets/src/tool_pch.h b/tests/projects/c++/precompiled_header_multiple_targets/src/tool_pch.h new file mode 100644 index 000000000..d66ed03f7 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/src/tool_pch.h @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/tests/projects/c++/precompiled_header_multiple_targets/test.lua b/tests/projects/c++/precompiled_header_multiple_targets/test.lua new file mode 100644 index 000000000..b57362078 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/test.lua @@ -0,0 +1,3 @@ +function main(t) + t:build() +end diff --git a/tests/projects/c++/precompiled_header_multiple_targets/xmake.lua b/tests/projects/c++/precompiled_header_multiple_targets/xmake.lua new file mode 100644 index 000000000..a3dacda41 --- /dev/null +++ b/tests/projects/c++/precompiled_header_multiple_targets/xmake.lua @@ -0,0 +1,38 @@ +add_rules("mode.debug", "mode.release") +set_languages("cxx11") + +-- Target 1: main executable +target("main") + set_kind("binary") + set_pcxxheader("src/common.h") + add_files("src/main.cpp") + add_deps("lib1", "lib2") + +-- Target 2: static library 1 +target("lib1") + set_kind("static") + set_pcxxheader("src/lib1_pch.h") + add_files("src/lib1.cpp") + +-- Target 3: static library 2 +target("lib2") + set_kind("static") + set_pcxxheader("src/lib2_pch.h") + add_files("src/lib2.cpp") + +-- Target 4: another executable with different PCH +target("tool") + set_kind("binary") + set_pcxxheader("src/tool_pch.h") + add_files("src/tool.cpp") + +-- Target 5: executable without PCH +target("simple") + set_kind("binary") + add_files("src/simple.cpp") + +-- Target 6: executable without PCH but depends on PCH library +target("consumer") + set_kind("binary") + add_files("src/consumer.cpp") + add_deps("lib1") -- cgit v1.3.1 From 5ed27569ffb41d7ce65a9185e26ad258bd2707fd Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 24 Jan 2026 22:09:55 +0800 Subject: improve pch --- xmake/rules/c++/precompiled_header/xmake.lua | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/precompiled_header/xmake.lua b/xmake/rules/c++/precompiled_header/xmake.lua index a2b08fe46..d67535cc6 100644 --- a/xmake/rules/c++/precompiled_header/xmake.lua +++ b/xmake/rules/c++/precompiled_header/xmake.lua @@ -22,19 +22,38 @@ rule("c.build.pcheader") on_config(function (target, opt) import("private.action.build.pcheader").config(target, "c", opt) end) - before_prepare(function (target, jobgraph, opt) + + before_build(function (target, jobgraph, opt) if not os.getenv("XMAKE_IN_COMPILE_COMMANDS_PROJECT_GENERATOR") then import("private.action.build.pcheader").build(target, jobgraph, "c", opt) end end, {jobgraph = true}) rule("c++.build.pcheader") - add_orders("c++.build.modules.scanner", "c++.build.pcheader", "c++.build.modules.builder") on_config(function (target, opt) import("private.action.build.pcheader").config(target, "cxx", opt) end) + + -- If the current target has a C++ modules file, + -- we can only compile it earlier in the before_prepare stage, + -- because the C++ modules will perform a complete dependency scan of + -- the C++ files in on_prepare and then build the dependency graph. + -- At this time, the pch header file must have already been generated. before_prepare(function (target, jobgraph, opt) - if not os.getenv("XMAKE_IN_COMPILE_COMMANDS_PROJECT_GENERATOR") then + local has_modules = target:data("cxx.has_modules") + if has_modules and not os.getenv("XMAKE_IN_COMPILE_COMMANDS_PROJECT_GENERATOR") then + import("private.action.build.pcheader").build(target, jobgraph, "cxx", opt) + end + end, {jobgraph = true}) + + -- To enable parallel compilation across targets + -- without blocking the compilation of other cpp files, + -- we perform this as much as possible during the before_build stage. + -- + -- @see: https://github.com/xmake-io/xmake/issues/4167 + before_build(function (target, jobgraph, opt) + local has_modules = target:data("cxx.has_modules") + if not has_modules then import("private.action.build.pcheader").build(target, jobgraph, "cxx", opt) end end, {jobgraph = true}) -- cgit v1.3.1 From 1532bf0e2acfe769c2545b3d3d4f35ed5556de24 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 24 Jan 2026 22:16:41 +0800 Subject: improve pch rules --- xmake/modules/private/action/build/pcheader.lua | 3 +++ xmake/rules/c++/precompiled_header/xmake.lua | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/build/pcheader.lua b/xmake/modules/private/action/build/pcheader.lua index 2e3210dca..4e984f62b 100644 --- a/xmake/modules/private/action/build/pcheader.lua +++ b/xmake/modules/private/action/build/pcheader.lua @@ -51,6 +51,9 @@ function config(target, langkind, opt) target:pcheaderfile_set(langkind, headerfile) end end + + -- enable precompiled header? + return true end end diff --git a/xmake/rules/c++/precompiled_header/xmake.lua b/xmake/rules/c++/precompiled_header/xmake.lua index d67535cc6..8bfdd09dd 100644 --- a/xmake/rules/c++/precompiled_header/xmake.lua +++ b/xmake/rules/c++/precompiled_header/xmake.lua @@ -20,7 +20,10 @@ rule("c.build.pcheader") on_config(function (target, opt) - import("private.action.build.pcheader").config(target, "c", opt) + import("private.action.build.pcheader") + if not pcheader.config(target, "c", opt) then + target:rule_enable("c.build.pcheader", false) + end end) before_build(function (target, jobgraph, opt) @@ -31,7 +34,10 @@ rule("c.build.pcheader") rule("c++.build.pcheader") on_config(function (target, opt) - import("private.action.build.pcheader").config(target, "cxx", opt) + import("private.action.build.pcheader") + if not pcheader.config(target, "cxx", opt) then + target:rule_enable("c++.build.pcheader", false) + end end) -- If the current target has a C++ modules file, -- cgit v1.3.1 From 6f2f989f19df66e73999ffaaffc69b8df1159a68 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 24 Jan 2026 22:21:01 +0800 Subject: improve objc pch --- xmake/rules/objc++/precompiled_header/xmake.lua | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/xmake/rules/objc++/precompiled_header/xmake.lua b/xmake/rules/objc++/precompiled_header/xmake.lua index ed0eda0a4..5dafb0e84 100644 --- a/xmake/rules/objc++/precompiled_header/xmake.lua +++ b/xmake/rules/objc++/precompiled_header/xmake.lua @@ -20,18 +20,32 @@ rule("objc.build.pcheader") on_config(function (target, opt) - import("private.action.build.pcheader").config(target, "m", opt) + import("private.action.build.pcheader") + if not pcheader.config(target, "m", opt) then + target:rule_enable("objc.build.pcheader", false) + end end) - before_prepare(function (target, jobgraph, opt) - import("private.action.build.pcheader").build(target, jobgraph, "m", opt) + + before_build(function (target, jobgraph, opt) + if not os.getenv("XMAKE_IN_COMPILE_COMMANDS_PROJECT_GENERATOR") then + import("private.action.build.pcheader").build(target, jobgraph, "m", opt) + end end, {jobgraph = true}) rule("objc++.build.pcheader") add_orders("objc++.build.pcheader", "c++.build.modules.builder") on_config(function (target, opt) - import("private.action.build.pcheader").config(target, "mxx", opt) + import("private.action.build.pcheader") + if not pcheader.config(target, "mxx", opt) then + target:rule_enable("objc++.build.pcheader", false) + end end) - before_prepare(function (target, jobgraph, opt) + + -- Since Objective-C typically does not have C++ modules, + -- we can always enable parallel compilation across targets + -- without blocking the compilation of other cpp files, + -- we perform this as much as possible during the before_build stage. + before_build(function (target, jobgraph, opt) import("private.action.build.pcheader").build(target, jobgraph, "mxx", opt) end, {jobgraph = true}) -- cgit v1.3.1