summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-02 18:48:13 +0800
committerGitHub <[email protected]>2025-12-02 18:48:13 +0800
commit5b0d381ec72cf946c07e76a36542eb1be169ffb1 (patch)
treed535a2fc0001f0e54844d5c5336ecb1f8a9e02a2
parentbc7caf95a9cfdefed930937e8450997a4cdc8191 (diff)
parent6e5b053e337cf53fabaee9c650e2b215118c95b0 (diff)
Merge pull request #7091 from xmake-io/debug
Add dynamic debugging support for msvc
-rw-r--r--xmake/core/project/policy.lua2
-rw-r--r--xmake/rules/c++/config/dynamic_debugging.lua102
-rw-r--r--xmake/rules/c++/config/main.lua10
3 files changed, 111 insertions, 3 deletions
diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua
index 6a3393cce..1cecfd01a 100644
--- a/xmake/core/project/policy.lua
+++ b/xmake/core/project/policy.lua
@@ -108,6 +108,8 @@ function policy.policies()
["build.c++.gcc.modules.cxx11abi"] = {description = "Force to enable new cxx11 abi in C++ modules for gcc. (deprecated)", type = "boolean"},
-- Set the default vs runtime, e.g. MT, MD
["build.c++.msvc.runtime"] = {description = "Set the default vs runtime.", type = "string", values = {"MT", "MD"}},
+ -- Enable C++ Dynamic Debugging for MSVC (requires MSVC toolset 14.44+, x64 only, incompatible with LTCG/PGO/OPT-ICF).
+ ["build.c++.dynamic_debugging"] = {description = "Enable C++ Dynamic Debugging for MSVC (requires MSVC toolset 14.44+, x64 only, incompatible with LTCG/PGO/OPT-ICF).", type = "boolean"},
-- Enable cuda device link
["build.cuda.devlink"] = {description = "Enable Cuda devlink.", type = "boolean"},
-- Enable linker output, e.g. show -Wl,--print-memory-usage output for gcc/g++
diff --git a/xmake/rules/c++/config/dynamic_debugging.lua b/xmake/rules/c++/config/dynamic_debugging.lua
new file mode 100644
index 000000000..fcc496ce6
--- /dev/null
+++ b/xmake/rules/c++/config/dynamic_debugging.lua
@@ -0,0 +1,102 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, Xmake Open Source Community.
+--
+-- @author ruki
+-- @file dynamic_debugging.lua
+--
+
+-- imports
+import("core.project.project")
+import("core.tool.toolchain")
+import("core.base.semver")
+
+-- add dynamic debugging support
+-- @see https://devblogs.microsoft.com/cppblog/cpp-dynamic-debugging-full-debuggability-for-optimized-builds/
+-- https://github.com/xmake-io/xmake/issues/6258
+function main(target, sourcekind)
+ -- check if dynamic debugging is enabled
+ local enabled = target:policy("build.c++.dynamic_debugging")
+ if enabled == nil then
+ enabled = project.policy("build.c++.dynamic_debugging")
+ end
+ if not enabled then
+ return
+ end
+
+ -- only support Windows platform
+ if not target:is_plat("windows") then
+ return
+ end
+
+ -- only support x64 architecture
+ if not target:is_arch("x64", "x86_64") then
+ wprint("C++ Dynamic Debugging only supports x64 architecture, current arch: %s", target:arch())
+ return
+ end
+
+ -- check MSVC toolchain (only support cl, not clang-cl or clang)
+ if not target:has_tool(sourcekind, "cl") then
+ return
+ end
+
+ -- check MSVC version (requires Visual Studio 2022 Version 17.14 Preview 2+, toolset 14.44+)
+ local msvc = target:toolchain("msvc")
+ if not msvc or not msvc:check() then
+ wprint("MSVC toolchain not found for C++ Dynamic Debugging")
+ return
+ end
+
+ local vcvars = msvc:config("vcvars")
+ if not vcvars or not vcvars.VCToolsVersion then
+ wprint("MSVC VCToolsVersion not found for C++ Dynamic Debugging")
+ return
+ end
+
+ local version = vcvars.VCToolsVersion
+ if not version or semver.compare(version, "14.44") < 0 then
+ wprint("C++ Dynamic Debugging requires Visual Studio 2022 Version 17.14 Preview 2+ (MSVC toolset 14.44+), found: %s", version or "unknown")
+ return
+ end
+
+ -- check incompatible optimizations
+ local has_lto = target:policy("build.optimization.lto") or project.policy("build.optimization.lto")
+ if has_lto then
+ wprint("C++ Dynamic Debugging is incompatible with LTO, disabling LTO")
+ target:set("policy", "build.optimization.lto", false)
+ end
+
+ -- check for /GL flag (added by optimize="smallest")
+ local optimize = target:get("optimize")
+ if optimize == "smallest" then
+ wprint("C++ Dynamic Debugging is incompatible with optimize=\"smallest\" (which adds /GL flag), consider using optimize=\"fastest\" or optimize=\"faster\" instead")
+ end
+
+ -- /dynamicdeopt requires debug symbols (/Zi or /Z7)
+ if not target:get("symbols") then
+ target:set("symbols", "debug")
+ end
+
+ -- get flag name for sourcekind (only support cc and cxx)
+ local cflag = sourcekind == "cxx" and "cxxflags" or "cflags"
+
+ -- add /dynamicdeopt compiler flag
+ target:add(cflag, "/dynamicdeopt", {force = true})
+
+ -- add /DYNAMICDEOPT linker flag
+ target:add("ldflags", "/DYNAMICDEOPT", {force = true})
+ target:add("shflags", "/DYNAMICDEOPT", {force = true})
+end
+
diff --git a/xmake/rules/c++/config/main.lua b/xmake/rules/c++/config/main.lua
index 78d1362af..dce7cff6b 100644
--- a/xmake/rules/c++/config/main.lua
+++ b/xmake/rules/c++/config/main.lua
@@ -19,9 +19,10 @@
--
-- imports
-import("basic", {alias = "config_basic"})
-import("optimization", {alias = "config_optimization"})
-import("sanitizer", {alias = "config_sanitizer"})
+import("rules.c++.config.basic", {rootdir = os.programdir(), alias = "config_basic"})
+import("rules.c++.config.optimization", {rootdir = os.programdir(), alias = "config_optimization"})
+import("rules.c++.config.sanitizer", {rootdir = os.programdir(), alias = "config_sanitizer"})
+import("rules.c++.config.dynamic_debugging", {rootdir = os.programdir(), alias = "config_dynamic_debugging"})
-- main entry
function main(target, sourcekind)
@@ -29,6 +30,9 @@ function main(target, sourcekind)
-- config basic configs
config_basic(target, sourcekind)
+ -- config dynamic debugging configs (must be before optimization to disable incompatible flags)
+ config_dynamic_debugging(target, sourcekind)
+
-- config optimization configs
config_optimization(target, sourcekind)