summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-02-07 00:52:20 +0800
committerruki <[email protected]>2026-02-07 00:52:20 +0800
commit791292f2ee65a4ca8566c3e7a38cbcbf965ddd08 (patch)
treeb3d1bd6944c3e704828d904a0698fb8e44bf328d
parent6007059c47a51d5847772fb68e357e4869ba85b3 (diff)
improve run policy and missing dll
-rw-r--r--core/src/xmake/engine.c2
-rw-r--r--tests/projects/windows/windows_links/xmake.lua2
-rw-r--r--xmake/actions/run/main.lua14
-rw-r--r--xmake/core/base/os.lua5
-rw-r--r--xmake/core/base/process.lua43
-rw-r--r--xmake/core/project/policy.lua4
-rw-r--r--xmake/core/sandbox/modules/os.lua65
-rw-r--r--xmake/core/sandbox/modules/winos.lua2
8 files changed, 69 insertions, 68 deletions
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c
index ccd77e7e5..1a542bc7c 100644
--- a/core/src/xmake/engine.c
+++ b/core/src/xmake/engine.c
@@ -486,7 +486,7 @@ static luaL_Reg const g_winos_functions[] = {
{ "registry_values", xm_winos_registry_values },
{ "short_path", xm_winos_short_path },
{ "processes", xm_winos_processes },
- { "seterrormode", xm_winos_set_error_mode },
+ { "set_error_mode", xm_winos_set_error_mode },
{ tb_null, tb_null },
};
#endif
diff --git a/tests/projects/windows/windows_links/xmake.lua b/tests/projects/windows/windows_links/xmake.lua
index dcb7e4e2c..57ae03712 100644
--- a/tests/projects/windows/windows_links/xmake.lua
+++ b/tests/projects/windows/windows_links/xmake.lua
@@ -1,6 +1,6 @@
add_rules("mode.debug", "mode.release")
-set_policy("run.gui_error_dialogs", true)
+set_policy("run.windows_error_dialog", true)
target("foo")
set_kind("shared")
diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua
index 899df8d61..87ba5f098 100644
--- a/xmake/actions/run/main.lua
+++ b/xmake/actions/run/main.lua
@@ -59,11 +59,23 @@ function _do_run_target(target)
targetfile = wine.program
end
+ -- enable GUI error dialogs (Windows only)
+ -- @see https://github.com/xmake-io/xmake/issues/7176
+ local old_errormode
+ if target:policy("run.windows_error_dialog") and winos.set_error_mode then
+ old_errormode = winos.set_error_mode(0)
+ end
+
-- debugging?
if option.get("debug") then
debugger.run(targetfile, args, {curdir = rundir, addenvs = addenvs, setenvs = setenvs})
else
- os.execv(targetfile, args, {curdir = rundir, detach = option.get("detach"), addenvs = addenvs, setenvs = setenvs, winos_error_mode_gui = target:policy("run.gui_error_dialogs")})
+ os.execv(targetfile, args, {curdir = rundir, detach = option.get("detach"), addenvs = addenvs, setenvs = setenvs})
+ end
+
+ -- restore error mode
+ if old_errormode then
+ winos.set_error_mode(old_errormode)
end
end
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index ae730738e..d20cd671a 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -1020,6 +1020,9 @@ function os.execv(program, argv, opt)
local waitok, status = proc:wait(opt.timeout or -1)
if waitok > 0 then
ok = status
+ if ok and ok ~= 0 then
+ errors = process.get_exit_errors(filename, ok)
+ end
elseif waitok == 0 and opt.timeout then
proc:kill()
waitok, status = proc:wait(-1)
@@ -1093,7 +1096,7 @@ function os.iorunv(program, argv, opt)
if argv then
cmd = cmd .. " " .. os.args(argv)
end
- errors = string.format("cannot runv(%s), %s", cmd, errors and errors or "unknown reason")
+ errors = string.format("cannot runv(%s), %s", cmd, errors or "unknown reason")
end
-- get output and error data
diff --git a/xmake/core/base/process.lua b/xmake/core/base/process.lua
index 5436115ed..bea469346 100644
--- a/xmake/core/base/process.lua
+++ b/xmake/core/base/process.lua
@@ -271,5 +271,48 @@ function process.openv(program, argv, opt)
end
end
+-- get missing dlls
+function process._get_missing_dlls(program)
+
+ -- get paths
+ local pathenv = os.getenv("PATH") or ""
+ local paths = path.splitenv(pathenv)
+ table.insert(paths, 1, path.directory(program))
+
+ -- find missing dlls
+ local missing = {}
+ local binutils = require("base/binutils")
+ local imports = binutils.deplibs(program) or {}
+ for _, dll in ipairs(imports) do
+ local found = false
+ for _, p in ipairs(paths) do
+ if os.isfile(path.join(p, dll)) then
+ found = true
+ break
+ end
+ end
+ if not found then
+ table.insert(missing, dll)
+ end
+ end
+ return missing
+end
+
+-- get process exit errors
+function process.get_exit_errors(program, exitcode)
+ if is_host("windows") then
+ -- DLL is missing, 0xC0000135
+ if exitcode == -1073741515 and os.isexec(program) then
+ local missing_dlls = process._get_missing_dlls(program)
+ if #missing_dlls > 0 then
+ errors = string.format("system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because the following DLLs were not found:\n - %s\nPlease check your PATH environment variable or copy the missing DLLs to the executable directory.", table.concat(missing_dlls, "\n - "))
+ else
+ errors = string.format("system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because a dependent DLL was not found.\nPlease check your PATH environment variable or copy the missing DLL to the executable directory.")
+ end
+ end
+ end
+end
+
+
-- return module: process
return process
diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua
index 3f24d9a0f..0fdd70831 100644
--- a/xmake/core/project/policy.lua
+++ b/xmake/core/project/policy.lua
@@ -34,8 +34,6 @@ function policy.policies()
local policies = policy._POLICIES
if not policies then
policies = {
- -- Enable/Disable Windows Error Reporting Dialogs
- ["run.gui_error_dialogs"] = {description = "Enable Windows Error Reporting Dialogs during execution.", default = false, type = "boolean"},
-- We will check and ignore all unsupported flags by default, but we can also pass `{force = true}` to force to set flags, e.g. add_ldflags("-static", {force = true})
["check.auto_ignore_flags"] = {description = "Enable check and ignore unsupported flags automatically.", default = true, type = "boolean"},
-- We will map gcc flags to the current compiler and linker by default.
@@ -129,6 +127,8 @@ function policy.policies()
["windows.manifest.uac.ui"] = {description = "Enable ui access for windows UAC.", type = "boolean"},
-- Automatically build before running
["run.autobuild"] = {description = "Automatically build before running.", type = "boolean"},
+ -- Enable/Disable Windows Error Reporting Dialogs
+ ["run.windows_error_dialog"] = {description = "Enable Windows Error Reporting Dialogs during execution.", default = false, type = "boolean"},
-- Enable install rpath
["install.rpath"] = {description = "Enable install rpath.", default = true, type = "boolean"},
-- Strip package libraries for installation
diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua
index ce2cf6504..8fe76987e 100644
--- a/xmake/core/sandbox/modules/os.lua
+++ b/xmake/core/sandbox/modules/os.lua
@@ -21,12 +21,10 @@
-- load modules
local io = require("base/io")
local os = require("base/os")
-local path = require("base/path")
local utils = require("base/utils")
local xmake = require("base/xmake")
local option = require("base/option")
local semver = require("base/semver")
-local binutils = require("base/binutils")
local scheduler = require("base/scheduler")
local sandbox = require("sandbox/sandbox")
local vformat = require("sandbox/modules/vformat")
@@ -332,43 +330,14 @@ function sandbox_os.exec(cmd, ...)
local ok, errors = os.exec(cmd)
if ok ~= 0 then
if ok ~= nil then
- errors = string.format("exec(%s) failed(%d)", cmd, ok)
+ errors = string.format("exec(%s) failed(%d), %s", cmd, ok, errors or "unknown reason")
else
- errors = string.format("cannot exec(%s), %s", cmd, errors and errors or "unknown reason")
+ errors = string.format("cannot exec(%s), %s", cmd, errors or "unknown reason")
end
os.raise(errors)
end
end
--- get missing dlls
-function sandbox_os._get_missing_dlls(program)
-
- -- check
- assert(program)
-
- -- get paths
- local pathenv = os.getenv("PATH") or ""
- local paths = path.splitenv(pathenv)
- table.insert(paths, 1, path.directory(program))
-
- -- find missing dlls
- local missing = {}
- local imports = binutils.deplibs(program) or {}
- for _, dll in ipairs(imports) do
- local found = false
- for _, p in ipairs(paths) do
- if os.isfile(path.join(p, dll)) then
- found = true
- break
- end
- end
- if not found then
- table.insert(missing, dll)
- end
- end
- return missing
-end
-
-- execute command with arguments list
function sandbox_os.execv(program, argv, opt)
@@ -391,24 +360,7 @@ function sandbox_os.execv(program, argv, opt)
-- run it
opt = opt or {}
-
- -- check policy for GUI error dialogs (Windows only)
- local old_mode
- local winos
- if os.is_host("windows") and opt.winos_error_mode_gui then
- winos = require("sandbox/modules/winos")
- if winos.seterrormode then
- old_mode = winos.seterrormode(0)
- end
- end
-
local ok, errors = os.execv(program, argv, opt)
-
- -- restore error mode
- if old_mode then
- winos.seterrormode(old_mode)
- end
-
if ok ~= 0 and not opt.try then
-- get command
@@ -419,18 +371,9 @@ function sandbox_os.execv(program, argv, opt)
-- get errors
if ok ~= nil then
- if ok == -1073741515 then -- 0xC0000135
- local missing_dlls = sandbox_os._get_missing_dlls(program)
- if #missing_dlls > 0 then
- errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because the following DLLs were not found:\n - %s\nPlease check your PATH environment variable or copy the missing DLLs to the executable directory.", cmd, ok, table.concat(missing_dlls, "\n - "))
- else
- errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because a dependent DLL was not found.\nPlease check your PATH environment variable or copy the missing DLL to the executable directory.", cmd, ok)
- end
- else
- errors = string.format("execv(%s) failed(%d)", cmd, ok)
- end
+ errors = string.format("execv(%s) failed(%d), %s", cmd, ok, errors or "unknown reason")
else
- errors = string.format("cannot execv(%s), %s", cmd, errors and errors or "unknown reason")
+ errors = string.format("cannot execv(%s), %s", cmd, errors or "unknown reason")
end
os.raise(errors)
end
diff --git a/xmake/core/sandbox/modules/winos.lua b/xmake/core/sandbox/modules/winos.lua
index 862ed9a8b..2ed01245d 100644
--- a/xmake/core/sandbox/modules/winos.lua
+++ b/xmake/core/sandbox/modules/winos.lua
@@ -35,7 +35,7 @@ sandbox_winos.logical_drives = winos.logical_drives
sandbox_winos.cmdargv = winos.cmdargv
sandbox_winos.processes = winos.processes
sandbox_winos.inherit_handles_safely = winos.inherit_handles_safely
-sandbox_winos.seterrormode = winos.seterrormode
+sandbox_winos.set_error_mode = winos.set_error_mode
-- get windows system version
function sandbox_winos.version()