diff options
| author | ruki <[email protected]> | 2026-01-25 10:20:26 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-25 10:20:26 +0800 |
| commit | c3989a33c7644a43d4c3cc5567e4e117785bc67d (patch) | |
| tree | 063cbf139fc243e6b872d84b2b465b152ef6febb | |
| parent | 0e77fe915b391f51d2460f33dca632171e0612ca (diff) | |
| parent | 6f2f989f19df66e73999ffaaffc69b8df1159a68 (diff) | |
Merge pull request #7262 from xmake-io/pch
Improve pch concurrently to the other targets
15 files changed, 177 insertions, 10 deletions
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 <iostream> +#include <string> +#include <vector> 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 <iostream> + +// 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<int> 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 <algorithm> +#include <numeric> +#include <vector> 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<int, std::string> data = {{1, "one"}, {2, "two"}, {3, "three"}}; + std::set<int> 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 <map> +#include <set> +#include <string> 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<int> 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 <iostream> +#include <string> + +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 <fstream> +#include <sstream> +#include <iostream> 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") 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 a2b08fe46..8bfdd09dd 100644 --- a/xmake/rules/c++/precompiled_header/xmake.lua +++ b/xmake/rules/c++/precompiled_header/xmake.lua @@ -20,21 +20,46 @@ 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_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) + 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, + -- 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}) 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}) |
