diff options
| author | ruki <[email protected]> | 2026-04-08 16:46:28 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-08 16:46:28 +0800 |
| commit | 3a91a8b27ebc9d40656750615a3606e5fe971fc9 (patch) | |
| tree | 9d76ca97662897854f57b38d09861c6e8449ab73 | |
| parent | ad2ec59e16d975d0fae054649ad360fe85031012 (diff) | |
| parent | 9d962c7502d997218a99ea00491475ca8d568066 (diff) | |
Merge pull request #7449 from Akaps316/codex/fix-modules-private-dep-bmis
fix(c++/modules): avoid leaking private dep flags to rebuilt BMIs
8 files changed, 95 insertions, 8 deletions
diff --git a/core/xpack.lua b/core/xpack.lua index 9f1721e5a..a0288004a 100644 --- a/core/xpack.lua +++ b/core/xpack.lua @@ -40,14 +40,15 @@ xpack("xmake") else local arch = package:arch() local url_7z = "https://github.com/xmake-mirror/7zip/releases/download/24.08/7z24.08-" .. arch .. ".zip" - local curl_version = "8.11.0_4" - local url_curl = "https://curl.se/windows/dl-" .. curl_version .. "/curl-" .. curl_version + local curl_version = "8.19.0_6" + local curl_version_win32 = "8.14.1_1" + local url_curl if package:is_arch("x64", "x86_64") then - url_curl = url_curl .. "-win64-mingw.zip" + url_curl = "https://curl.se/windows/dl-" .. curl_version .. "/curl-" .. curl_version .. "-win64-mingw.zip" elseif package:is_arch("arm64") then - url_curl = url_curl .. "-win64a-mingw.zip" + url_curl = "https://curl.se/windows/dl-" .. curl_version .. "/curl-" .. curl_version .. "-win64a-mingw.zip" else - url_curl = url_curl .. "-win32-mingw.zip" + url_curl = "https://curl.se/windows/dl-" .. curl_version_win32 .. "/curl-" .. curl_version_win32 .. "-win32-mingw.zip" end local archive_7z = path.join(package:builddir(), "7z.zip") local archive_curl = path.join(package:builddir(), "curl.zip") diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/src/include/public_config.h b/tests/projects/c++/modules/reuse_strict_private_defines/src/include/public_config.h new file mode 100644 index 000000000..3ceb5dcd5 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/src/include/public_config.h @@ -0,0 +1,3 @@ +#pragma once + +#define PUBLIC_CONFIG_VALUE 0 diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/src/main.cpp b/tests/projects/c++/modules/reuse_strict_private_defines/src/main.cpp new file mode 100644 index 000000000..5b477f2d6 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/src/main.cpp @@ -0,0 +1,5 @@ +import mod; + +int main() { + return foo(); +} diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.cpp b/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.cpp new file mode 100644 index 000000000..aaf40d855 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.cpp @@ -0,0 +1,9 @@ +module; + +#include <public_config.h> + +module mod; + +int foo() { + return PUBLIC_CONFIG_VALUE; +} diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.mpp b/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.mpp new file mode 100644 index 000000000..b55b834a7 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/src/mod.mpp @@ -0,0 +1,3 @@ +export module mod; + +export int foo(); diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/test.lua b/tests/projects/c++/modules/reuse_strict_private_defines/test.lua new file mode 100644 index 000000000..6e3304b68 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/test.lua @@ -0,0 +1,47 @@ +inherit(".test_base") +import("utils.ci.is_running", {alias = "ci_is_running"}) + +local CLANG_MIN_VER = is_subhost("windows") and "19" or "17" +local GCC_MIN_VER = "11" +local MSVC_MIN_VER = "14.29" + +local PRIVATE_DEFINE = "PRIVATE_DEP_DEFINE_DO_NOT_PROPAGATE" +local PUBLIC_SYSINCLUDEDIR = path.translate("src/include") + +function _build() + local flags = "" + if ci_is_running() then + flags = "-vD" + end + local leaked = false + local missing_sysincludedir = true + local outdata = try { function () return os.iorun("xmake -rv") end } + if outdata then + for line in outdata:gmatch("[^\r\n]+") do + if line:find("Consumer", 1, true) then + if line:find(PRIVATE_DEFINE, 1, true) then + leaked = true + end + if line:find(PUBLIC_SYSINCLUDEDIR, 1, true) then + missing_sysincludedir = false + end + end + end + if leaked then + raise("Private dependency defines leaked into Consumer module rebuilds under reuse.strict\n%s", outdata) + end + if missing_sysincludedir then + raise("Missing public sysincludedir in Consumer module rebuilds under reuse.strict\n%s", outdata) + end + else + -- maybe build failed, we need to see verbose errors + os.run("xmake " .. flags) + end +end + +function main(_) + local clang_options = {compiler = "clang", version = CLANG_MIN_VER, build = _build} + local gcc_options = {compiler = "gcc", version = GCC_MIN_VER, build = _build} + local msvc_options = {version = MSVC_MIN_VER, build = _build} + run_tests(clang_options, gcc_options, msvc_options) +end diff --git a/tests/projects/c++/modules/reuse_strict_private_defines/xmake.lua b/tests/projects/c++/modules/reuse_strict_private_defines/xmake.lua new file mode 100644 index 000000000..77314cf47 --- /dev/null +++ b/tests/projects/c++/modules/reuse_strict_private_defines/xmake.lua @@ -0,0 +1,16 @@ +add_rules("mode.debug", "mode.release") + +set_languages("c++20") + +target("Producer") + set_kind("static") + add_defines("PRIVATE_DEP_DEFINE_DO_NOT_PROPAGATE") + add_sysincludedirs("src/include", {public = true}) + add_files("src/mod.mpp", {public = true}) + add_files("src/mod.cpp") + +target("Consumer") + set_kind("binary") + set_policy("build.c++.modules.reuse.strict", true) + add_deps("Producer") + add_files("src/main.cpp") diff --git a/xmake/rules/c++/modules/scanner.lua b/xmake/rules/c++/modules/scanner.lua index 72adea260..22b96bb0d 100644 --- a/xmake/rules/c++/modules/scanner.lua +++ b/xmake/rules/c++/modules/scanner.lua @@ -283,9 +283,12 @@ function _get_targetdeps_modules(target) fileconfig.undefines = _fileconfig.undefines fileconfig.includedirs = _fileconfig.includedirs end - fileconfig.defines = table.join(fileconfig.defines or {}, dep:get("defines") or {}) - fileconfig.undefines = table.join(fileconfig.undefines or {}, dep:get("undefines") or {}) - fileconfig.includedirs = table.join(fileconfig.includedirs or {}, dep:get("includedirs") or {}) + -- only propagate public/interface defines, not private ones + -- e.g. add_defines("LIB") is private and should not leak into the consumer's BMI + -- @see https://github.com/xmake-io/xmake/issues/7436 + fileconfig.defines = table.join(fileconfig.defines or {}, dep:get("defines", {interface = true}) or {}) + fileconfig.undefines = table.join(fileconfig.undefines or {}, dep:get("undefines", {interface = true}) or {}) + fileconfig.includedirs = table.join(fileconfig.includedirs or {}, dep:get("includedirs", {interface = true}) or {}) if not dep:is_phony() then if target:namespace() == dep:namespace() then fileconfig.from_dep = dep:name() |
