diff options
| author | ruki <[email protected]> | 2026-02-07 00:52:20 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2026-02-07 00:52:20 +0800 |
| commit | 791292f2ee65a4ca8566c3e7a38cbcbf965ddd08 (patch) | |
| tree | b3d1bd6944c3e704828d904a0698fb8e44bf328d | |
| parent | 6007059c47a51d5847772fb68e357e4869ba85b3 (diff) | |
improve run policy and missing dll
| -rw-r--r-- | core/src/xmake/engine.c | 2 | ||||
| -rw-r--r-- | tests/projects/windows/windows_links/xmake.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/run/main.lua | 14 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 5 | ||||
| -rw-r--r-- | xmake/core/base/process.lua | 43 | ||||
| -rw-r--r-- | xmake/core/project/policy.lua | 4 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/os.lua | 65 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/winos.lua | 2 |
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() |
