diff options
| author | ruki <[email protected]> | 2026-02-07 11:02:38 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-07 11:02:38 +0800 |
| commit | 15d8fed683b17f3bff4abb3d36f79fa291ac577c (patch) | |
| tree | 044a4a9b8b824cdb7aba3a513b28ae701e69cd16 | |
| parent | 4780a467c144f27a4c2f9923d030750d0f25f5a5 (diff) | |
| parent | 08f5b8a7bdac97cab8f5055a5ae9b066d2b18664 (diff) | |
Merge pull request #7302 from xmake-io/missdll
Improve run process errors
| -rw-r--r-- | core/src/xmake/engine.c | 2 | ||||
| -rw-r--r-- | core/src/xmake/winos/set_error_mode.c | 41 | ||||
| -rw-r--r-- | tests/projects/windows/windows_links/src/foo.c | 9 | ||||
| -rw-r--r-- | tests/projects/windows/windows_links/src/main.c | 21 | ||||
| -rw-r--r-- | tests/projects/windows/windows_links/xmake.lua | 20 | ||||
| -rw-r--r-- | xmake/actions/run/main.lua | 12 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 5 | ||||
| -rw-r--r-- | xmake/core/base/process.lua | 52 | ||||
| -rw-r--r-- | xmake/core/project/policy.lua | 2 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/os.lua | 8 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/winos.lua | 1 |
11 files changed, 168 insertions, 5 deletions
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 9c02d8487..1a542bc7c 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -279,6 +279,7 @@ tb_int_t xm_winos_registry_keys(lua_State *lua); tb_int_t xm_winos_registry_values(lua_State *lua); tb_int_t xm_winos_short_path(lua_State *lua); tb_int_t xm_winos_processes(lua_State* lua); +tb_int_t xm_winos_set_error_mode(lua_State *lua); #endif // the utf8 functions @@ -485,6 +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 }, + { "set_error_mode", xm_winos_set_error_mode }, { tb_null, tb_null }, }; #endif diff --git a/core/src/xmake/winos/set_error_mode.c b/core/src/xmake/winos/set_error_mode.c new file mode 100644 index 000000000..ceff4684b --- /dev/null +++ b/core/src/xmake/winos/set_error_mode.c @@ -0,0 +1,41 @@ +/*!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 set_error_mode.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "set_error_mode" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +tb_int_t xm_winos_set_error_mode(lua_State *lua) { + tb_size_t mode = (tb_size_t)luaL_checkinteger(lua, 1); + lua_pushinteger(lua, (tb_int_t)SetErrorMode((UINT)mode)); + return 1; +} diff --git a/tests/projects/windows/windows_links/src/foo.c b/tests/projects/windows/windows_links/src/foo.c new file mode 100644 index 000000000..29b5a4334 --- /dev/null +++ b/tests/projects/windows/windows_links/src/foo.c @@ -0,0 +1,9 @@ +#include <stdio.h>
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {
+ printf("foo called\n");
+}
+
diff --git a/tests/projects/windows/windows_links/src/main.c b/tests/projects/windows/windows_links/src/main.c new file mode 100644 index 000000000..bc94c3f13 --- /dev/null +++ b/tests/projects/windows/windows_links/src/main.c @@ -0,0 +1,21 @@ +#include <windows.h>
+#include <psapi.h>
+#include <stdio.h>
+
+__declspec(dllimport) void foo();
+
+int main() {
+ PROCESS_MEMORY_COUNTERS pmc;
+ printf("Calling GetProcessMemoryInfo...\n");
+ if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
+ printf("PageFaultCount: %lu\n", pmc.PageFaultCount);
+ printf("WorkingSetSize: %lu\n", pmc.WorkingSetSize);
+ } else {
+ printf("GetProcessMemoryInfo failed (%lu)\n", GetLastError());
+ }
+ printf("Calling foo...\n");
+ foo();
+ printf("Done.\n");
+ return 0;
+}
+
diff --git a/tests/projects/windows/windows_links/xmake.lua b/tests/projects/windows/windows_links/xmake.lua new file mode 100644 index 000000000..57ae03712 --- /dev/null +++ b/tests/projects/windows/windows_links/xmake.lua @@ -0,0 +1,20 @@ +add_rules("mode.debug", "mode.release")
+
+set_policy("run.windows_error_dialog", true)
+
+target("foo")
+ set_kind("shared")
+ add_files("src/foo.c")
+
+target("test_foo_dll_presence")
+ set_kind("binary")
+ add_files("src/main.c")
+ add_deps("foo")
+ add_syslinks("psapi")
+ after_build(function (target)
+ local foo = target:dep("foo")
+ if foo then
+ os.tryrm(foo:targetfile())
+ end
+ end)
+
diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua index 39cbd4d6a..6ed59f3f1 100644 --- a/xmake/actions/run/main.lua +++ b/xmake/actions/run/main.lua @@ -88,12 +88,24 @@ 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}) end + + -- restore error mode + if old_errormode then + winos.set_error_mode(old_errormode) + end end -- run target 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..692a6360f 100644 --- a/xmake/core/base/process.lua +++ b/xmake/core/base/process.lua @@ -271,5 +271,57 @@ function process.openv(program, argv, opt) end end +-- get missing dlls +function process._get_missing_dlls(program) + local missing = {} + if not os.isexec(program) then + return missing + end + + -- get paths + local pathenv = os.getenv("PATH") or "" + local paths = path.splitenv(pathenv) + table.insert(paths, 1, path.directory(program)) + + -- find missing dlls + local sandbox_module = require("sandbox/modules/import/core/sandbox/module") + local get_depend_libraries = sandbox_module.import("utils.binary.deplibs", {anonymous = true}) + local imports = get_depend_libraries(program, {recursive = true}) or {} + for i, dll in ipairs(imports) do + imports[i] = path.filename(dll) + end + 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) + local errors + if os.is_host("windows") then + -- DLL is missing, 0xC0000135 + if exitcode == -1073741515 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 + return errors +end + + -- return module: process return process diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 5123f0a5c..0fdd70831 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -127,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 aebb3cfb0..8fe76987e 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -330,9 +330,9 @@ 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 @@ -371,9 +371,9 @@ function sandbox_os.execv(program, argv, opt) -- get errors if ok ~= nil then - errors = string.format("execv(%s) failed(%d)", cmd, ok) + 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 eddcf91d4..2ed01245d 100644 --- a/xmake/core/sandbox/modules/winos.lua +++ b/xmake/core/sandbox/modules/winos.lua @@ -35,6 +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.set_error_mode = winos.set_error_mode -- get windows system version function sandbox_winos.version() |
