summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-01-25 10:20:26 +0800
committerGitHub <[email protected]>2026-01-25 10:20:26 +0800
commitc3989a33c7644a43d4c3cc5567e4e117785bc67d (patch)
tree063cbf139fc243e6b872d84b2b465b152ef6febb
parent0e77fe915b391f51d2460f33dca632171e0612ca (diff)
parent6f2f989f19df66e73999ffaaffc69b8df1159a68 (diff)
Merge pull request #7262 from xmake-io/pch
Improve pch concurrently to the other targets
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/common.h3
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/consumer.cpp11
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/lib1.cpp7
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/lib1_pch.h3
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/lib2.cpp12
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/lib2_pch.h3
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/main.cpp19
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/simple.cpp8
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/tool.cpp15
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/src/tool_pch.h3
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/test.lua3
-rw-r--r--tests/projects/c++/precompiled_header_multiple_targets/xmake.lua38
-rw-r--r--xmake/modules/private/action/build/pcheader.lua3
-rw-r--r--xmake/rules/c++/precompiled_header/xmake.lua35
-rw-r--r--xmake/rules/objc++/precompiled_header/xmake.lua24
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})