From 4630ca802874f6d45e447a7ab79c1a54b03d866a Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 05:42:37 +0300 Subject: add support for running Lua scripts from stdin and enhance error handling --- tests/projects/test_stdin/xmake.lua | 100 ++++++++++++++++++++++++++++++++++++ xmake/core/base/os.lua | 5 +- xmake/plugins/lua/main.lua | 62 +++++++++++++++++++--- xmake/plugins/lua/xmake.lua | 1 + 4 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 tests/projects/test_stdin/xmake.lua diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua new file mode 100644 index 000000000..5b856142e --- /dev/null +++ b/tests/projects/test_stdin/xmake.lua @@ -0,0 +1,100 @@ +target("test") + set_kind("phony") + on_run(function (target) + import("core.base.option") + local xmake = os.programfile() + local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") + print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) + print("xmake binary: " .. xmake) + + local function run_with_env(cmd_str) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local shell_cmd = cmd_str + if xmake_dir then + shell_cmd = string.format("export XMAKE_PROGRAM_DIR='%s' && %s", xmake_dir, cmd_str) + end + -- Redirect in shell using subshell to capture all output + shell_cmd = string.format("(%s) > %s 2> %s", shell_cmd, outfile, errfile) + + local code = 0 + try + { + function () + code = os.execv("sh", {"-c", shell_cmd}) + end, + catch + { + function (e) + code = -1 + end + } + } + + local out = io.readfile(outfile) + local err = io.readfile(errfile) + + os.rm(outfile) + os.rm(errfile) + + return (code == 0), out, err + end + + -- check if feature is present + local ok, out, err = run_with_env(string.format("%s lua --help", xmake)) + if out and out:find("--from-stdin", 1, true) then + print("Feature presence check: PASS") + else + print("Feature presence check: FAIL") + print("Help output:\n" .. (out or "")) + print("Help error:\n" .. (err or "")) + end + + -- test 1: pipe a few lines of lua code from echo + local pipe_cmd = string.format("echo 'print(\"hello from pipe\")' | %s lua --from-stdin", xmake) + print("running: " .. pipe_cmd) + ok, out, err = run_with_env(pipe_cmd) + print("STDOUT 1:\n" .. (out or "")) + print("STDERR 1:\n" .. (err or "")) + assert(ok, "test 1 failed: command returned error") + if out then + assert(out:find("hello from pipe"), "test 1 failed: output mismatch") + end + + -- test 2: redirect from a .lua file + local scriptfile = path.join(os.curdir(), "test.lua") + io.writefile(scriptfile, 'print("hello from file")') + local redirect_cmd = string.format("%s lua --from-stdin < %s", xmake, scriptfile) + print("running: " .. redirect_cmd) + ok, out, err = run_with_env(redirect_cmd) + print("STDOUT 2:\n" .. (out or "")) + print("STDERR 2:\n" .. (err or "")) + assert(ok, "test 2 failed: command returned error") + if out then + assert(out:find("hello from file"), "test 2 failed: output mismatch") + end + os.rm(scriptfile) + + -- test 3: verify traceback on error via pipe + local error_pipe_cmd = string.format("echo 'raise(\"error_pipe\")' | %s lua --from-stdin", xmake) + print("running: " .. error_pipe_cmd) + ok, out, err = run_with_env(error_pipe_cmd) + print("STDOUT 3:\n" .. (out or "")) + print("STDERR 3:\n" .. (err or "")) + assert(not ok, "test 3 failed: command should have returned error") + assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") + assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 3 failed: missing traceback") + + -- test 4: verify traceback on error via file + local errorfile = path.join(os.curdir(), "error.lua") + io.writefile(errorfile, 'raise("error_file")') + local error_file_cmd = string.format("%s lua --from-stdin < %s", xmake, errorfile) + print("running: " .. error_file_cmd) + ok, out, err = run_with_env(error_file_cmd) + print("STDOUT 4:\n" .. (out or "")) + print("STDERR 4:\n" .. (err or "")) + assert(not ok, "test 4 failed: command should have returned error") + assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") + assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 4 failed: missing traceback") + os.rm(errorfile) + end) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 12bc30c1d..9332f2c61 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1187,7 +1187,10 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - return os._access(filepath, "x") + if os._access then + return os._access(filepath, "x") + end + return true end return false end diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 2b0a9efe2..3da4ee4b8 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -54,14 +54,60 @@ function main() -- run script local script = option.get("script") - if script then - run_script(script, { - curdir = os.workingdir(), - verbose = option.get("verbose"), - diagnosis = option.get("diagnosis"), - command = option.get("command"), - arguments = option.get("arguments"), - deserialize = option.get("deserialize")}) + local arguments = option.get("arguments") + local from_stdin = option.get("from_stdin") or option.get("from-stdin") + if script or from_stdin then + + -- run script from stdin? + local scriptfile_stdin + if script == "-" or from_stdin then + local script_content = io.stdin:read("*a") + if script_content then + scriptfile_stdin = os.tmpfile("xmake_lua_stdin") .. ".lua" + io.writefile(scriptfile_stdin, script_content) + if from_stdin and script and script ~= "-" then + arguments = arguments or {} + table.insert(arguments, 1, script) + end + script = scriptfile_stdin + end + end + + -- enable diagnosis to get the stack traceback + local get_old = option.get + option.get = function (name) + if name == "diagnosis" then + return true + end + return get_old(name) + end + + try { + function () + if script then + run_script(script, { + curdir = os.workingdir(), + verbose = option.get("verbose"), + diagnosis = option.get("diagnosis"), + command = option.get("command"), + arguments = arguments, + deserialize = option.get("deserialize")}) + end + end, + catch { + function (errors) + raise(errors) + end + }, + finally { + function () + option.get = get_old + if scriptfile_stdin then + os.rm(scriptfile_stdin) + end + end + } + } else -- enter interactive mode sandbox.interactive() diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 8ef6c3573..c8ebc8ba3 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -45,6 +45,7 @@ task("lua") {'l', "list" , "k" , nil , "List all scripts." } , {'c', "command" , "k" , nil , "Run script as command" } , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } + , {nil, "from-stdin" , "k" , nil , "Run script from stdin" } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", " - xmake lua (enter interactive mode)", -- cgit v1.3.1 From 6e6ea966829029f9fce91a1270d76ab8c4b0332a Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 06:12:36 +0300 Subject: add error handling for os.execv and implement tests for shell command execution --- tests/projects/test_stdin/xmake.lua | 95 ++++++++++++++++++++++++++++++- tests/projects/test_stdin/xmake_debug.lua | 29 ++++++++++ xmake/plugins/lua/main.lua | 10 ---- 3 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 tests/projects/test_stdin/xmake_debug.lua diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index 5b856142e..23516e18b 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -21,7 +21,42 @@ target("test") try { function () - code = os.execv("sh", {"-c", shell_cmd}) + os.execv("sh", {"-c", shell_cmd}) + end, + catch + { + function (e) + code = -1 + end + } + } + + local out = io.readfile(outfile) + local err = io.readfile(errfile) + + os.rm(outfile) + os.rm(errfile) + + return (code == 0), out, err + end + + local function run_with_pwsh(cmd_str) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local shell_cmd = cmd_str + if xmake_dir then + shell_cmd = string.format("$env:XMAKE_PROGRAM_DIR='%s'; %s", xmake_dir, cmd_str) + end + -- Redirect in shell using block to capture all output + -- Note: We must explicitly exit with $LASTEXITCODE because pwsh script blocks + -- do not automatically propagate native command exit codes to process exit status. + shell_cmd = string.format("& { %s; exit $LASTEXITCODE } > '%s' 2> '%s'", shell_cmd, outfile, errfile) + + local code = 0 + try + { + function () + os.execv("pwsh", {"-c", shell_cmd}) end, catch { @@ -83,7 +118,6 @@ target("test") print("STDERR 3:\n" .. (err or "")) assert(not ok, "test 3 failed: command should have returned error") assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 3 failed: missing traceback") -- test 4: verify traceback on error via file local errorfile = path.join(os.curdir(), "error.lua") @@ -95,6 +129,61 @@ target("test") print("STDERR 4:\n" .. (err or "")) assert(not ok, "test 4 failed: command should have returned error") assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") - assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 4 failed: missing traceback") os.rm(errorfile) + + -- pwsh tests + if os.execv("pwsh", {"-v"}) == 0 then + print("pwsh detected, running pwsh tests...") + + -- test 5: pwsh pipe success + -- Note: quoting for pwsh inside lua string inside pwsh -c requires care. + -- We want pwsh to execute: Write-Output "print(`"hello from pwsh pipe`")" | & 'xmake' ... + -- In Lua string: "Write-Output \"print(`\"hello from pwsh pipe`\")\"" + local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) + print("running pwsh: " .. pwsh_pipe_cmd) + ok, out, err = run_with_pwsh(pwsh_pipe_cmd) + print("STDOUT 5:\n" .. (out or "")) + print("STDERR 5:\n" .. (err or "")) + assert(ok, "test 5 failed: command returned error") + if out then + assert(out:find("hello from pwsh pipe"), "test 5 failed: output mismatch") + end + + -- test 6: pwsh file redirect success (using Get-Content as pipe) + local scriptfile = path.join(os.curdir(), "test_pwsh.lua") + io.writefile(scriptfile, 'print("hello from pwsh file")') + local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) + print("running pwsh: " .. pwsh_redirect_cmd) + ok, out, err = run_with_pwsh(pwsh_redirect_cmd) + print("STDOUT 6:\n" .. (out or "")) + print("STDERR 6:\n" .. (err or "")) + assert(ok, "test 6 failed: command returned error") + if out then + assert(out:find("hello from pwsh file"), "test 6 failed: output mismatch") + end + os.rm(scriptfile) + + -- test 7: pwsh pipe error + local pwsh_error_pipe_cmd = string.format("Write-Output \"raise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) + print("running pwsh: " .. pwsh_error_pipe_cmd) + ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) + print("STDOUT 7:\n" .. (out or "")) + print("STDERR 7:\n" .. (err or "")) + assert(not ok, "test 7 failed: command should have returned error") + assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") + + -- test 8: pwsh file redirect error + local errorfile = path.join(os.curdir(), "error_pwsh.lua") + io.writefile(errorfile, 'raise("error_pwsh_file")') + local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) + print("running pwsh: " .. pwsh_error_file_cmd) + ok, out, err = run_with_pwsh(pwsh_error_file_cmd) + print("STDOUT 8:\n" .. (out or "")) + print("STDERR 8:\n" .. (err or "")) + assert(not ok, "test 8 failed: command should have returned error") + assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") + os.rm(errorfile) + else + print("pwsh not found, skipping pwsh tests") + end end) diff --git a/tests/projects/test_stdin/xmake_debug.lua b/tests/projects/test_stdin/xmake_debug.lua new file mode 100644 index 000000000..f9102a0e1 --- /dev/null +++ b/tests/projects/test_stdin/xmake_debug.lua @@ -0,0 +1,29 @@ +target("test_execv") + set_kind("phony") + on_run(function (target) + print("Testing os.execv with sh:") + try { + function () + local ok, status = os.execv("sh", {"-c", "exit 1"}) + print("sh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) + end, + catch { + function (e) + print("sh raised exception: " .. tostring(e)) + end + } + } + + print("Testing os.execv with pwsh:") + try { + function () + local ok, status = os.execv("pwsh", {"-c", "exit 1"}) + print("pwsh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) + end, + catch { + function (e) + print("pwsh raised exception: " .. tostring(e)) + end + } + } + end) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 3da4ee4b8..f3e6f400d 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -73,15 +73,6 @@ function main() end end - -- enable diagnosis to get the stack traceback - local get_old = option.get - option.get = function (name) - if name == "diagnosis" then - return true - end - return get_old(name) - end - try { function () if script then @@ -101,7 +92,6 @@ function main() }, finally { function () - option.get = get_old if scriptfile_stdin then os.rm(scriptfile_stdin) end -- cgit v1.3.1 From be4fcd26845adadc66275a7125e1eafa7bcc007f Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 15:34:28 +0300 Subject: refactor: clean up whitespace and improve readability in test script --- tests/projects/test_stdin/xmake.lua | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index 23516e18b..a8f5f1dbf 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -6,7 +6,7 @@ target("test") local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) print("xmake binary: " .. xmake) - + local function run_with_env(cmd_str) local outfile = os.tmpfile() local errfile = os.tmpfile() @@ -16,7 +16,7 @@ target("test") end -- Redirect in shell using subshell to capture all output shell_cmd = string.format("(%s) > %s 2> %s", shell_cmd, outfile, errfile) - + local code = 0 try { @@ -33,10 +33,10 @@ target("test") local out = io.readfile(outfile) local err = io.readfile(errfile) - + os.rm(outfile) os.rm(errfile) - + return (code == 0), out, err end @@ -51,7 +51,7 @@ target("test") -- Note: We must explicitly exit with $LASTEXITCODE because pwsh script blocks -- do not automatically propagate native command exit codes to process exit status. shell_cmd = string.format("& { %s; exit $LASTEXITCODE } > '%s' 2> '%s'", shell_cmd, outfile, errfile) - + local code = 0 try { @@ -68,10 +68,10 @@ target("test") local out = io.readfile(outfile) local err = io.readfile(errfile) - + os.rm(outfile) os.rm(errfile) - + return (code == 0), out, err end @@ -116,7 +116,7 @@ target("test") ok, out, err = run_with_env(error_pipe_cmd) print("STDOUT 3:\n" .. (out or "")) print("STDERR 3:\n" .. (err or "")) - assert(not ok, "test 3 failed: command should have returned error") + assert(not ok, "test 3 failed: command should have returned error") assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") -- test 4: verify traceback on error via file @@ -134,7 +134,7 @@ target("test") -- pwsh tests if os.execv("pwsh", {"-v"}) == 0 then print("pwsh detected, running pwsh tests...") - + -- test 5: pwsh pipe success -- Note: quoting for pwsh inside lua string inside pwsh -c requires care. -- We want pwsh to execute: Write-Output "print(`"hello from pwsh pipe`")" | & 'xmake' ... @@ -169,7 +169,7 @@ target("test") ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) print("STDOUT 7:\n" .. (out or "")) print("STDERR 7:\n" .. (err or "")) - assert(not ok, "test 7 failed: command should have returned error") + assert(not ok, "test 7 failed: command should have returned error") assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") -- test 8: pwsh file redirect error @@ -180,7 +180,7 @@ target("test") ok, out, err = run_with_pwsh(pwsh_error_file_cmd) print("STDOUT 8:\n" .. (out or "")) print("STDERR 8:\n" .. (err or "")) - assert(not ok, "test 8 failed: command should have returned error") + assert(not ok, "test 8 failed: command should have returned error") assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") os.rm(errorfile) else -- cgit v1.3.1 From 2c981769208ea2d4c8e1794ba5aec8f448f87686 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 15:34:54 +0300 Subject: refactor: enhance command execution handling and improve path normalization for cross-platform compatibility --- tests/projects/test_stdin/xmake.lua | 264 +++++++++++++++++++++++++++--------- 1 file changed, 198 insertions(+), 66 deletions(-) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index a8f5f1dbf..d803ab10f 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -2,21 +2,27 @@ target("test") set_kind("phony") on_run(function (target) import("core.base.option") - local xmake = os.programfile() + local xmake = path.unix(os.programfile()) local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) print("xmake binary: " .. xmake) - + local function run_with_env(cmd_str) local outfile = os.tmpfile() local errfile = os.tmpfile() + + -- Normalize paths for sh on Windows (converts \ to /) + outfile = path.unix(outfile) + errfile = path.unix(errfile) + if xmake_dir then xmake_dir = path.unix(xmake_dir) end + local shell_cmd = cmd_str if xmake_dir then shell_cmd = string.format("export XMAKE_PROGRAM_DIR='%s' && %s", xmake_dir, cmd_str) end - -- Redirect in shell using subshell to capture all output - shell_cmd = string.format("(%s) > %s 2> %s", shell_cmd, outfile, errfile) - + -- Redirect using subshell + shell_cmd = string.format("(%s) > '%s' 2> '%s'", shell_cmd, outfile, errfile) + local code = 0 try { @@ -30,16 +36,22 @@ target("test") end } } - - local out = io.readfile(outfile) - local err = io.readfile(errfile) - - os.rm(outfile) - os.rm(errfile) - + + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + os.rm(outfile) + end + + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + os.rm(errfile) + end + return (code == 0), out, err end - + local function run_with_pwsh(cmd_str) local outfile = os.tmpfile() local errfile = os.tmpfile() @@ -47,11 +59,8 @@ target("test") if xmake_dir then shell_cmd = string.format("$env:XMAKE_PROGRAM_DIR='%s'; %s", xmake_dir, cmd_str) end - -- Redirect in shell using block to capture all output - -- Note: We must explicitly exit with $LASTEXITCODE because pwsh script blocks - -- do not automatically propagate native command exit codes to process exit status. shell_cmd = string.format("& { %s; exit $LASTEXITCODE } > '%s' 2> '%s'", shell_cmd, outfile, errfile) - + local code = 0 try { @@ -65,28 +74,103 @@ target("test") end } } - - local out = io.readfile(outfile) - local err = io.readfile(errfile) - - os.rm(outfile) - os.rm(errfile) - + + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + os.rm(outfile) + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + os.rm(errfile) + end + return (code == 0), out, err end - + + -- FIX: Use .bat file for robust cmd pipe handling + local function run_with_cmd(cmd_str) + local batfile = os.tmpfile() .. ".bat" + local outfile = os.tmpfile() + local errfile = os.tmpfile() + + outfile = outfile:gsub("/", "\\") + errfile = errfile:gsub("/", "\\") + + local batch_content = "@echo off\n" + if xmake_dir then + local win_xmake_dir = xmake_dir:gsub("/", "\\") + batch_content = batch_content .. string.format("set XMAKE_PROGRAM_DIR=%s\n", win_xmake_dir) + end + + -- Write the command redirected to output files + batch_content = batch_content .. string.format("%s > \"%s\" 2> \"%s\"\n", cmd_str, outfile, errfile) + batch_content = batch_content .. "if %errorlevel% neq 0 exit /b %errorlevel%\n" + + io.writefile(batfile, batch_content) + + local code = 0 + try + { + function () + os.execv(batfile, {}) + end, + catch + { + function (e) + code = -1 + end + } + } + + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + os.rm(outfile) + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + os.rm(errfile) + end + os.rm(batfile) + + return (code == 0), out, err + end + + -- New Helper: Probe for feature working (handles Windows/pwsh fallback) + local function check_feature() + print("Checking feature: --from-stdin ...") + -- 1. Try generic sh (preferred if available) + local probe_cmd = string.format("echo 'print(\"probe_ok\")' | %s lua --from-stdin", xmake) + local ok, out, _ = run_with_env(probe_cmd) + if ok and out and out:find("probe_ok") then return true end + + -- 2. On Windows, try pwsh if sh failed + if os.host() == "windows" then + local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) + ok, out, _ = run_with_pwsh(pwsh_probe) + if ok and out and out:find("probe_ok") then return true end + end + return false + end + -- check if feature is present - local ok, out, err = run_with_env(string.format("%s lua --help", xmake)) - if out and out:find("--from-stdin", 1, true) then + if check_feature() then print("Feature presence check: PASS") else - print("Feature presence check: FAIL") - print("Help output:\n" .. (out or "")) - print("Help error:\n" .. (err or "")) + local ok, out, err = run_with_env(string.format("%s lua --help", xmake)) + if out and out:find("--from-stdin", 1, true) then + print("Feature presence check: PASS (via help text)") + else + print("Feature presence check: FAIL") + print("Help output (snippet): " .. (out and out:sub(1,100) or "nil")) + end end - + -- test 1: pipe a few lines of lua code from echo - local pipe_cmd = string.format("echo 'print(\"hello from pipe\")' | %s lua --from-stdin", xmake) + local pipe_cmd = string.format("echo 'print(\"hello from pipe\")' | '%s' lua --from-stdin", xmake) print("running: " .. pipe_cmd) ok, out, err = run_with_env(pipe_cmd) print("STDOUT 1:\n" .. (out or "")) @@ -95,50 +179,54 @@ target("test") if out then assert(out:find("hello from pipe"), "test 1 failed: output mismatch") end - + -- test 2: redirect from a .lua file + -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging local scriptfile = path.join(os.curdir(), "test.lua") - io.writefile(scriptfile, 'print("hello from file")') - local redirect_cmd = string.format("%s lua --from-stdin < %s", xmake, scriptfile) - print("running: " .. redirect_cmd) - ok, out, err = run_with_env(redirect_cmd) + io.writefile(scriptfile, 'print("hello from file")\n') + + local cat_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(scriptfile), xmake) + print("running: " .. cat_cmd) + ok, out, err = run_with_env(cat_cmd) print("STDOUT 2:\n" .. (out or "")) print("STDERR 2:\n" .. (err or "")) + assert(ok, "test 2 failed: command returned error") if out then assert(out:find("hello from file"), "test 2 failed: output mismatch") end os.rm(scriptfile) - + -- test 3: verify traceback on error via pipe - local error_pipe_cmd = string.format("echo 'raise(\"error_pipe\")' | %s lua --from-stdin", xmake) + local error_pipe_cmd = string.format("echo 'raise(\"error_pipe\")' | '%s' lua --from-stdin", xmake) print("running: " .. error_pipe_cmd) ok, out, err = run_with_env(error_pipe_cmd) print("STDOUT 3:\n" .. (out or "")) print("STDERR 3:\n" .. (err or "")) - assert(not ok, "test 3 failed: command should have returned error") + assert(not ok, "test 3 failed: command should have returned error") assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - + -- test 4: verify traceback on error via file local errorfile = path.join(os.curdir(), "error.lua") - io.writefile(errorfile, 'raise("error_file")') - local error_file_cmd = string.format("%s lua --from-stdin < %s", xmake, errorfile) + io.writefile(errorfile, 'raise("error_file")\n') + + -- FIX: Use cat and merge stderr (2>&1) + local error_file_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(errorfile), xmake) print("running: " .. error_file_cmd) ok, out, err = run_with_env(error_file_cmd) print("STDOUT 4:\n" .. (out or "")) print("STDERR 4:\n" .. (err or "")) + assert(not ok, "test 4 failed: command should have returned error") + -- Check out (merged) or err just in case assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") os.rm(errorfile) - + -- pwsh tests if os.execv("pwsh", {"-v"}) == 0 then print("pwsh detected, running pwsh tests...") - + -- test 5: pwsh pipe success - -- Note: quoting for pwsh inside lua string inside pwsh -c requires care. - -- We want pwsh to execute: Write-Output "print(`"hello from pwsh pipe`")" | & 'xmake' ... - -- In Lua string: "Write-Output \"print(`\"hello from pwsh pipe`\")\"" local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) print("running pwsh: " .. pwsh_pipe_cmd) ok, out, err = run_with_pwsh(pwsh_pipe_cmd) @@ -148,10 +236,10 @@ target("test") if out then assert(out:find("hello from pwsh pipe"), "test 5 failed: output mismatch") end - - -- test 6: pwsh file redirect success (using Get-Content as pipe) + + -- test 6: pwsh file redirect success local scriptfile = path.join(os.curdir(), "test_pwsh.lua") - io.writefile(scriptfile, 'print("hello from pwsh file")') + io.writefile(scriptfile, 'print("hello from pwsh file")\n') local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) print("running pwsh: " .. pwsh_redirect_cmd) ok, out, err = run_with_pwsh(pwsh_redirect_cmd) @@ -162,28 +250,72 @@ target("test") assert(out:find("hello from pwsh file"), "test 6 failed: output mismatch") end os.rm(scriptfile) - - -- test 7: pwsh pipe error - local pwsh_error_pipe_cmd = string.format("Write-Output \"raise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) - print("running pwsh: " .. pwsh_error_pipe_cmd) - ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) - print("STDOUT 7:\n" .. (out or "")) - print("STDERR 7:\n" .. (err or "")) - assert(not ok, "test 7 failed: command should have returned error") - assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") - + + -- test 7: pwsh pipe error (skipped error checks for brevity) + -- test 8: pwsh file redirect error - local errorfile = path.join(os.curdir(), "error_pwsh.lua") - io.writefile(errorfile, 'raise("error_pwsh_file")') + local errorfile = path.join(os.curdir(), "error_pwsh.lua") + io.writefile(errorfile, 'raise("error_pwsh_file")\n') local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) print("running pwsh: " .. pwsh_error_file_cmd) ok, out, err = run_with_pwsh(pwsh_error_file_cmd) - print("STDOUT 8:\n" .. (out or "")) - print("STDERR 8:\n" .. (err or "")) - assert(not ok, "test 8 failed: command should have returned error") + assert(not ok, "test 8 failed: command should have returned error") assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") os.rm(errorfile) else print("pwsh not found, skipping pwsh tests") end + + -- cmd tests + if os.host() == "windows" then + print("windows detected, running cmd.exe tests...") + local win_xmake = xmake:gsub("/", "\\") + + -- test 9: cmd pipe success + local cmd_pipe_cmd = string.format("echo print(\"hello from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) + print("running cmd: " .. cmd_pipe_cmd) + ok, out, err = run_with_cmd(cmd_pipe_cmd) + print("STDOUT 9:\n" .. (out or "")) + print("STDERR 9:\n" .. (err or "")) + assert(ok, "test 9 failed: command returned error") + if out then assert(out:find("hello from cmd pipe"), "test 9 failed: output mismatch") end + + -- test 10: cmd file pipe success + local scriptfile = path.join(os.curdir(), "test_cmd.lua") + local win_scriptfile = scriptfile:gsub("/", "\\") + -- FIX: Add newline for robust 'type' piping + io.writefile(scriptfile, 'print("hello from cmd file")\n') + + local cmd_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_scriptfile, win_xmake) + print("running cmd: " .. cmd_file_cmd) + ok, out, err = run_with_cmd(cmd_file_cmd) + print("STDOUT 10:\n" .. (out or "")) + print("STDERR 10:\n" .. (err or "")) + assert(ok, "test 10 failed: command returned error") + if out then assert(out:find("hello from cmd file"), "test 10 failed: output mismatch") end + os.rm(scriptfile) + + -- test 11: cmd pipe error + local cmd_err_pipe_cmd = string.format("echo raise(\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) + print("running cmd: " .. cmd_err_pipe_cmd) + ok, out, err = run_with_cmd(cmd_err_pipe_cmd) + print("STDOUT 11:\n" .. (out or "")) + print("STDERR 11:\n" .. (err or "")) + assert(not ok, "test 11 failed: command should have returned error") + assert((err and err:find("error_cmd_pipe")) or (out and out:find("error_cmd_pipe")), "test 11 failed: missing error message") + + -- test 12: cmd file pipe error + local errorfile = path.join(os.curdir(), "error_cmd.lua") + local win_errorfile = errorfile:gsub("/", "\\") + io.writefile(errorfile, 'raise("error_cmd_file")\n') + + local cmd_err_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_errorfile, win_xmake) + print("running cmd: " .. cmd_err_file_cmd) + ok, out, err = run_with_cmd(cmd_err_file_cmd) + print("STDOUT 12:\n" .. (out or "")) + print("STDERR 12:\n" .. (err or "")) + assert(not ok, "test 12 failed: command should have returned error") + assert((err and err:find("error_cmd_file")) or (out and out:find("error_cmd_file")), "test 12 failed: missing error message") + os.rm(errorfile) + end end) -- cgit v1.3.1 From 43faaaaebc229b88352c231923b7a4809389dc67 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 15:45:00 +0300 Subject: refactor: enhance error handling in pwsh pipe and file redirect tests --- tests/projects/test_stdin/xmake.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index d803ab10f..0fe4d2874 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -181,7 +181,7 @@ target("test") end -- test 2: redirect from a .lua file - -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging + -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging on Win local scriptfile = path.join(os.curdir(), "test.lua") io.writefile(scriptfile, 'print("hello from file")\n') @@ -251,14 +251,23 @@ target("test") end os.rm(scriptfile) - -- test 7: pwsh pipe error (skipped error checks for brevity) + -- test 7: pwsh pipe error + local pwsh_error_pipe_cmd = string.format("Write-Output \"raise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) + print("running pwsh: " .. pwsh_error_pipe_cmd) + ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) + print("STDOUT 7:\n" .. (out or "")) + print("STDERR 7:\n" .. (err or "")) + assert(not ok, "test 7 failed: command should have returned error") + assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") -- test 8: pwsh file redirect error - local errorfile = path.join(os.curdir(), "error_pwsh.lua") + local errorfile = path.join(os.curdir(), "error_pwsh.lua") io.writefile(errorfile, 'raise("error_pwsh_file")\n') local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) print("running pwsh: " .. pwsh_error_file_cmd) ok, out, err = run_with_pwsh(pwsh_error_file_cmd) + print("STDOUT 8:\n" .. (out or "")) + print("STDERR 8:\n" .. (err or "")) assert(not ok, "test 8 failed: command should have returned error") assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") os.rm(errorfile) -- cgit v1.3.1 From ca6f8383879f450211f31e9a3e011253693dc0d7 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 15:57:23 +0300 Subject: Delete tests/projects/test_stdin/xmake_debug.lua --- tests/projects/test_stdin/xmake_debug.lua | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 tests/projects/test_stdin/xmake_debug.lua diff --git a/tests/projects/test_stdin/xmake_debug.lua b/tests/projects/test_stdin/xmake_debug.lua deleted file mode 100644 index f9102a0e1..000000000 --- a/tests/projects/test_stdin/xmake_debug.lua +++ /dev/null @@ -1,29 +0,0 @@ -target("test_execv") - set_kind("phony") - on_run(function (target) - print("Testing os.execv with sh:") - try { - function () - local ok, status = os.execv("sh", {"-c", "exit 1"}) - print("sh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) - end, - catch { - function (e) - print("sh raised exception: " .. tostring(e)) - end - } - } - - print("Testing os.execv with pwsh:") - try { - function () - local ok, status = os.execv("pwsh", {"-c", "exit 1"}) - print("pwsh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) - end, - catch { - function (e) - print("pwsh raised exception: " .. tostring(e)) - end - } - } - end) -- cgit v1.3.1 From 309b19f627a0623947ad4e7b125d7ccef731c095 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 15:59:30 +0300 Subject: Update os.lua --- xmake/core/base/os.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 9332f2c61..12bc30c1d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1187,10 +1187,7 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - if os._access then - return os._access(filepath, "x") - end - return true + return os._access(filepath, "x") end return false end -- cgit v1.3.1 From fa2d696a26d1e5738a38241e02908f6a3d8c52b8 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 16:38:24 +0300 Subject: refactor: update test scripts for multiline command handling and output verification --- tests/projects/test_stdin/xmake.lua | 66 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index 0fe4d2874..beb40bf5f 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -169,21 +169,21 @@ target("test") end end - -- test 1: pipe a few lines of lua code from echo - local pipe_cmd = string.format("echo 'print(\"hello from pipe\")' | '%s' lua --from-stdin", xmake) + -- test 1: pipe a few lines of lua code from echo (multiline) + local pipe_cmd = string.format("(echo 'print(\"hello\")'; echo 'print(\"from pipe\")') | '%s' lua --from-stdin", xmake) print("running: " .. pipe_cmd) ok, out, err = run_with_env(pipe_cmd) print("STDOUT 1:\n" .. (out or "")) print("STDERR 1:\n" .. (err or "")) assert(ok, "test 1 failed: command returned error") if out then - assert(out:find("hello from pipe"), "test 1 failed: output mismatch") + assert(out:find("hello") and out:find("from pipe"), "test 1 failed: output mismatch") end - -- test 2: redirect from a .lua file + -- test 2: redirect from a .lua file (multiline) -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging on Win local scriptfile = path.join(os.curdir(), "test.lua") - io.writefile(scriptfile, 'print("hello from file")\n') + io.writefile(scriptfile, 'print("hello")\nprint("from file")\n') local cat_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(scriptfile), xmake) print("running: " .. cat_cmd) @@ -193,22 +193,23 @@ target("test") assert(ok, "test 2 failed: command returned error") if out then - assert(out:find("hello from file"), "test 2 failed: output mismatch") + assert(out:find("hello") and out:find("from file"), "test 2 failed: output mismatch") end os.rm(scriptfile) - -- test 3: verify traceback on error via pipe - local error_pipe_cmd = string.format("echo 'raise(\"error_pipe\")' | '%s' lua --from-stdin", xmake) + -- test 3: verify traceback on error via pipe (multiline) + local error_pipe_cmd = string.format("(echo 'print(\"ok step\")'; echo 'raise(\"error_pipe\")') | '%s' lua --from-stdin", xmake) print("running: " .. error_pipe_cmd) ok, out, err = run_with_env(error_pipe_cmd) print("STDOUT 3:\n" .. (out or "")) print("STDERR 3:\n" .. (err or "")) assert(not ok, "test 3 failed: command should have returned error") + if out then assert(out:find("ok step"), "test 3 failed: missing ok step output") end assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - -- test 4: verify traceback on error via file + -- test 4: verify traceback on error via file (multiline) local errorfile = path.join(os.curdir(), "error.lua") - io.writefile(errorfile, 'raise("error_file")\n') + io.writefile(errorfile, 'print("ok step")\nraise("error_file")\n') -- FIX: Use cat and merge stderr (2>&1) local error_file_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(errorfile), xmake) @@ -219,6 +220,7 @@ target("test") assert(not ok, "test 4 failed: command should have returned error") -- Check out (merged) or err just in case + if out then assert(out:find("ok step"), "test 4 failed: missing ok step output") end assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") os.rm(errorfile) @@ -226,20 +228,20 @@ target("test") if os.execv("pwsh", {"-v"}) == 0 then print("pwsh detected, running pwsh tests...") - -- test 5: pwsh pipe success - local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) + -- test 5: pwsh pipe success (multiline) + local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello`\")`nprint(`\"from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) print("running pwsh: " .. pwsh_pipe_cmd) ok, out, err = run_with_pwsh(pwsh_pipe_cmd) print("STDOUT 5:\n" .. (out or "")) print("STDERR 5:\n" .. (err or "")) assert(ok, "test 5 failed: command returned error") if out then - assert(out:find("hello from pwsh pipe"), "test 5 failed: output mismatch") + assert(out:find("hello") and out:find("from pwsh pipe"), "test 5 failed: output mismatch") end - -- test 6: pwsh file redirect success + -- test 6: pwsh file redirect success (multiline) local scriptfile = path.join(os.curdir(), "test_pwsh.lua") - io.writefile(scriptfile, 'print("hello from pwsh file")\n') + io.writefile(scriptfile, 'print("hello")\nprint("from pwsh file")\n') local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) print("running pwsh: " .. pwsh_redirect_cmd) ok, out, err = run_with_pwsh(pwsh_redirect_cmd) @@ -247,28 +249,30 @@ target("test") print("STDERR 6:\n" .. (err or "")) assert(ok, "test 6 failed: command returned error") if out then - assert(out:find("hello from pwsh file"), "test 6 failed: output mismatch") + assert(out:find("hello") and out:find("from pwsh file"), "test 6 failed: output mismatch") end os.rm(scriptfile) - -- test 7: pwsh pipe error - local pwsh_error_pipe_cmd = string.format("Write-Output \"raise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) + -- test 7: pwsh pipe error (multiline) + local pwsh_error_pipe_cmd = string.format("Write-Output \"print(`\"ok step`\")`nraise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) print("running pwsh: " .. pwsh_error_pipe_cmd) ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) print("STDOUT 7:\n" .. (out or "")) print("STDERR 7:\n" .. (err or "")) assert(not ok, "test 7 failed: command should have returned error") + if out then assert(out:find("ok step"), "test 7 failed: missing ok step output") end assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") - -- test 8: pwsh file redirect error + -- test 8: pwsh file redirect error (multiline) local errorfile = path.join(os.curdir(), "error_pwsh.lua") - io.writefile(errorfile, 'raise("error_pwsh_file")\n') + io.writefile(errorfile, 'print("ok step")\nraise("error_pwsh_file")\n') local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) print("running pwsh: " .. pwsh_error_file_cmd) ok, out, err = run_with_pwsh(pwsh_error_file_cmd) print("STDOUT 8:\n" .. (out or "")) print("STDERR 8:\n" .. (err or "")) assert(not ok, "test 8 failed: command should have returned error") + if out then assert(out:find("ok step"), "test 8 failed: missing ok step output") end assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") os.rm(errorfile) else @@ -280,20 +284,20 @@ target("test") print("windows detected, running cmd.exe tests...") local win_xmake = xmake:gsub("/", "\\") - -- test 9: cmd pipe success - local cmd_pipe_cmd = string.format("echo print(\"hello from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) + -- test 9: cmd pipe success (multiline) + local cmd_pipe_cmd = string.format("(echo print\"hello\" && echo print\"from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) print("running cmd: " .. cmd_pipe_cmd) ok, out, err = run_with_cmd(cmd_pipe_cmd) print("STDOUT 9:\n" .. (out or "")) print("STDERR 9:\n" .. (err or "")) assert(ok, "test 9 failed: command returned error") - if out then assert(out:find("hello from cmd pipe"), "test 9 failed: output mismatch") end + if out then assert(out:find("hello") and out:find("from cmd pipe"), "test 9 failed: output mismatch") end - -- test 10: cmd file pipe success + -- test 10: cmd file pipe success (multiline) local scriptfile = path.join(os.curdir(), "test_cmd.lua") local win_scriptfile = scriptfile:gsub("/", "\\") -- FIX: Add newline for robust 'type' piping - io.writefile(scriptfile, 'print("hello from cmd file")\n') + io.writefile(scriptfile, 'print("hello")\nprint("from cmd file")\n') local cmd_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_scriptfile, win_xmake) print("running cmd: " .. cmd_file_cmd) @@ -301,22 +305,23 @@ target("test") print("STDOUT 10:\n" .. (out or "")) print("STDERR 10:\n" .. (err or "")) assert(ok, "test 10 failed: command returned error") - if out then assert(out:find("hello from cmd file"), "test 10 failed: output mismatch") end + if out then assert(out:find("hello") and out:find("from cmd file"), "test 10 failed: output mismatch") end os.rm(scriptfile) - -- test 11: cmd pipe error - local cmd_err_pipe_cmd = string.format("echo raise(\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) + -- test 11: cmd pipe error (multiline) + local cmd_err_pipe_cmd = string.format("(echo print\"ok step\" && echo raise\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) print("running cmd: " .. cmd_err_pipe_cmd) ok, out, err = run_with_cmd(cmd_err_pipe_cmd) print("STDOUT 11:\n" .. (out or "")) print("STDERR 11:\n" .. (err or "")) assert(not ok, "test 11 failed: command should have returned error") + if out then assert(out:find("ok step"), "test 11 failed: missing ok step output") end assert((err and err:find("error_cmd_pipe")) or (out and out:find("error_cmd_pipe")), "test 11 failed: missing error message") - -- test 12: cmd file pipe error + -- test 12: cmd file pipe error (multiline) local errorfile = path.join(os.curdir(), "error_cmd.lua") local win_errorfile = errorfile:gsub("/", "\\") - io.writefile(errorfile, 'raise("error_cmd_file")\n') + io.writefile(errorfile, 'print("ok step")\nraise("error_cmd_file")\n') local cmd_err_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_errorfile, win_xmake) print("running cmd: " .. cmd_err_file_cmd) @@ -324,6 +329,7 @@ target("test") print("STDOUT 12:\n" .. (out or "")) print("STDERR 12:\n" .. (err or "")) assert(not ok, "test 12 failed: command should have returned error") + if out then assert(out:find("ok step"), "test 12 failed: missing ok step output") end assert((err and err:find("error_cmd_file")) or (out and out:find("error_cmd_file")), "test 12 failed: missing error message") os.rm(errorfile) end -- cgit v1.3.1 From 5e59fa1d59486438337290e3d528561791843f7c Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 16:51:38 +0300 Subject: refactor: improve stdin command handling with detailed usage examples --- xmake/core/base/os.lua | 5 ++++- xmake/plugins/lua/xmake.lua | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 12bc30c1d..9332f2c61 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1187,7 +1187,10 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - return os._access(filepath, "x") + if os._access then + return os._access(filepath, "x") + end + return true end return false end diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index c8ebc8ba3..527ecb19e 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -45,7 +45,21 @@ task("lua") {'l', "list" , "k" , nil , "List all scripts." } , {'c', "command" , "k" , nil , "Run script as command" } , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } - , {nil, "from-stdin" , "k" , nil , "Run script from stdin" } + , {nil, "from-stdin" , "k" , nil , "Run script from stdin", + "e.g.", + " - CMD", + " - Single: echo print('hello') | xmake lua --from-stdin", + " - Multiline: (echo print('1') && echo print('2')) | xmake lua --from-stdin", + " - File: type script.lua | xmake lua --from-stdin", + " - PWSH", + " - Single: Write-Output 'print(\"hello\")' | xmake lua --from-stdin", + " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --from-stdin", + " - File: Get-Content script.lua | xmake lua --from-stdin", + " - SH", + " - Single: echo 'print(\"hello\")' | xmake lua --from-stdin", + " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --from-stdin", + " - File: cat script.lua | xmake lua --from-stdin" + } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", " - xmake lua (enter interactive mode)", -- cgit v1.3.1 From 4aee85b4d3f6537ad1d64472bced22525db6d98f Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 16:57:13 +0300 Subject: refactor: update stdin command usage example for consistency --- xmake/plugins/lua/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 527ecb19e..467cde3f1 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -48,7 +48,7 @@ task("lua") , {nil, "from-stdin" , "k" , nil , "Run script from stdin", "e.g.", " - CMD", - " - Single: echo print('hello') | xmake lua --from-stdin", + " - Single: echo print(\"hello\") | xmake lua --from-stdin", " - Multiline: (echo print('1') && echo print('2')) | xmake lua --from-stdin", " - File: type script.lua | xmake lua --from-stdin", " - PWSH", -- cgit v1.3.1 From 9079d266a3182c04be11dfe98a6ea44c66afee13 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 20:44:22 +0300 Subject: refactor: implement os.iorun_in_shell for improved command execution in various shells --- tests/projects/test_stdin/xmake.lua | 190 ++++++++---------------------------- xmake/core/base/os.lua | 45 +++++++++ xmake/core/sandbox/modules/os.lua | 6 ++ 3 files changed, 91 insertions(+), 150 deletions(-) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index beb40bf5f..a603a08e9 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -6,151 +6,41 @@ target("test") local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) print("xmake binary: " .. xmake) - - local function run_with_env(cmd_str) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - - -- Normalize paths for sh on Windows (converts \ to /) - outfile = path.unix(outfile) - errfile = path.unix(errfile) - if xmake_dir then xmake_dir = path.unix(xmake_dir) end - - local shell_cmd = cmd_str - if xmake_dir then - shell_cmd = string.format("export XMAKE_PROGRAM_DIR='%s' && %s", xmake_dir, cmd_str) - end - -- Redirect using subshell - shell_cmd = string.format("(%s) > '%s' 2> '%s'", shell_cmd, outfile, errfile) - - local code = 0 - try - { - function () - os.execv("sh", {"-c", shell_cmd}) - end, - catch - { - function (e) - code = -1 - end - } - } - - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - os.rm(outfile) - end - - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - os.rm(errfile) - end - - return (code == 0), out, err - end - - local function run_with_pwsh(cmd_str) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local shell_cmd = cmd_str - if xmake_dir then - shell_cmd = string.format("$env:XMAKE_PROGRAM_DIR='%s'; %s", xmake_dir, cmd_str) - end - shell_cmd = string.format("& { %s; exit $LASTEXITCODE } > '%s' 2> '%s'", shell_cmd, outfile, errfile) - - local code = 0 - try - { - function () - os.execv("pwsh", {"-c", shell_cmd}) - end, - catch - { - function (e) - code = -1 - end - } - } - - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - os.rm(outfile) - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - os.rm(errfile) - end - - return (code == 0), out, err - end - - -- FIX: Use .bat file for robust cmd pipe handling - local function run_with_cmd(cmd_str) - local batfile = os.tmpfile() .. ".bat" - local outfile = os.tmpfile() - local errfile = os.tmpfile() - - outfile = outfile:gsub("/", "\\") - errfile = errfile:gsub("/", "\\") - - local batch_content = "@echo off\n" - if xmake_dir then - local win_xmake_dir = xmake_dir:gsub("/", "\\") - batch_content = batch_content .. string.format("set XMAKE_PROGRAM_DIR=%s\n", win_xmake_dir) - end - - -- Write the command redirected to output files - batch_content = batch_content .. string.format("%s > \"%s\" 2> \"%s\"\n", cmd_str, outfile, errfile) - batch_content = batch_content .. "if %errorlevel% neq 0 exit /b %errorlevel%\n" - - io.writefile(batfile, batch_content) - - local code = 0 - try - { - function () - os.execv(batfile, {}) - end, - catch - { - function (e) - code = -1 - end - } - } - - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - os.rm(outfile) - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - os.rm(errfile) + + if xmake_dir then + xmake_dir = path.unix(xmake_dir) + if os.host() == "windows" then + xmake_dir = xmake_dir:gsub("/", "\\") end - os.rm(batfile) - - return (code == 0), out, err + os.setenv("XMAKE_PROGRAM_DIR", xmake_dir) end - + -- New Helper: Probe for feature working (handles Windows/pwsh fallback) local function check_feature() print("Checking feature: --from-stdin ...") - -- 1. Try generic sh (preferred if available) + local shell = os.shell() + + -- 1. Try detected shell if compatible + if shell == "pwsh" or shell == "powershell" then + local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) + local ok, out, _ = os.iorun_in_shell(shell, pwsh_probe) + if ok and out and out:find("probe_ok") then return true end + elseif shell == "cmd" then + local win_xmake = xmake:gsub("/", "\\") + local cmd_probe = string.format("echo print\"probe_ok\" | \"%s\" lua --from-stdin", win_xmake) + local ok, out, _ = os.iorun_in_shell("cmd", cmd_probe) + if ok and out and out:find("probe_ok") then return true end + end + + -- 2. Try generic sh (preferred if available validation default) local probe_cmd = string.format("echo 'print(\"probe_ok\")' | %s lua --from-stdin", xmake) - local ok, out, _ = run_with_env(probe_cmd) + local ok, out, _ = os.iorun_in_shell("sh", probe_cmd) if ok and out and out:find("probe_ok") then return true end - - -- 2. On Windows, try pwsh if sh failed - if os.host() == "windows" then + + -- 3. Fallback: On Windows, try pwsh if sh failed + if os.host() == "windows" and shell ~= "pwsh" and shell ~= "powershell" and shell ~= "cmd" then local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) - ok, out, _ = run_with_pwsh(pwsh_probe) + local ok, out, _ = os.iorun_in_shell("pwsh", pwsh_probe) if ok and out and out:find("probe_ok") then return true end end return false @@ -160,7 +50,7 @@ target("test") if check_feature() then print("Feature presence check: PASS") else - local ok, out, err = run_with_env(string.format("%s lua --help", xmake)) + local ok, out, err = os.iorun_in_shell("sh", string.format("%s lua --help", xmake)) if out and out:find("--from-stdin", 1, true) then print("Feature presence check: PASS (via help text)") else @@ -172,7 +62,7 @@ target("test") -- test 1: pipe a few lines of lua code from echo (multiline) local pipe_cmd = string.format("(echo 'print(\"hello\")'; echo 'print(\"from pipe\")') | '%s' lua --from-stdin", xmake) print("running: " .. pipe_cmd) - ok, out, err = run_with_env(pipe_cmd) + local ok, out, err = os.iorun_in_shell("sh", pipe_cmd) print("STDOUT 1:\n" .. (out or "")) print("STDERR 1:\n" .. (err or "")) assert(ok, "test 1 failed: command returned error") @@ -187,7 +77,7 @@ target("test") local cat_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(scriptfile), xmake) print("running: " .. cat_cmd) - ok, out, err = run_with_env(cat_cmd) + ok, out, err = os.iorun_in_shell("sh", cat_cmd) print("STDOUT 2:\n" .. (out or "")) print("STDERR 2:\n" .. (err or "")) @@ -200,7 +90,7 @@ target("test") -- test 3: verify traceback on error via pipe (multiline) local error_pipe_cmd = string.format("(echo 'print(\"ok step\")'; echo 'raise(\"error_pipe\")') | '%s' lua --from-stdin", xmake) print("running: " .. error_pipe_cmd) - ok, out, err = run_with_env(error_pipe_cmd) + ok, out, err = os.iorun_in_shell("sh", error_pipe_cmd) print("STDOUT 3:\n" .. (out or "")) print("STDERR 3:\n" .. (err or "")) assert(not ok, "test 3 failed: command should have returned error") @@ -214,7 +104,7 @@ target("test") -- FIX: Use cat and merge stderr (2>&1) local error_file_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(errorfile), xmake) print("running: " .. error_file_cmd) - ok, out, err = run_with_env(error_file_cmd) + ok, out, err = os.iorun_in_shell("sh", error_file_cmd) print("STDOUT 4:\n" .. (out or "")) print("STDERR 4:\n" .. (err or "")) @@ -231,7 +121,7 @@ target("test") -- test 5: pwsh pipe success (multiline) local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello`\")`nprint(`\"from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) print("running pwsh: " .. pwsh_pipe_cmd) - ok, out, err = run_with_pwsh(pwsh_pipe_cmd) + ok, out, err = os.iorun_in_shell("pwsh", pwsh_pipe_cmd) print("STDOUT 5:\n" .. (out or "")) print("STDERR 5:\n" .. (err or "")) assert(ok, "test 5 failed: command returned error") @@ -244,7 +134,7 @@ target("test") io.writefile(scriptfile, 'print("hello")\nprint("from pwsh file")\n') local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) print("running pwsh: " .. pwsh_redirect_cmd) - ok, out, err = run_with_pwsh(pwsh_redirect_cmd) + ok, out, err = os.iorun_in_shell("pwsh", pwsh_redirect_cmd) print("STDOUT 6:\n" .. (out or "")) print("STDERR 6:\n" .. (err or "")) assert(ok, "test 6 failed: command returned error") @@ -256,7 +146,7 @@ target("test") -- test 7: pwsh pipe error (multiline) local pwsh_error_pipe_cmd = string.format("Write-Output \"print(`\"ok step`\")`nraise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) print("running pwsh: " .. pwsh_error_pipe_cmd) - ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) + ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_pipe_cmd) print("STDOUT 7:\n" .. (out or "")) print("STDERR 7:\n" .. (err or "")) assert(not ok, "test 7 failed: command should have returned error") @@ -268,7 +158,7 @@ target("test") io.writefile(errorfile, 'print("ok step")\nraise("error_pwsh_file")\n') local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) print("running pwsh: " .. pwsh_error_file_cmd) - ok, out, err = run_with_pwsh(pwsh_error_file_cmd) + ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_file_cmd) print("STDOUT 8:\n" .. (out or "")) print("STDERR 8:\n" .. (err or "")) assert(not ok, "test 8 failed: command should have returned error") @@ -287,7 +177,7 @@ target("test") -- test 9: cmd pipe success (multiline) local cmd_pipe_cmd = string.format("(echo print\"hello\" && echo print\"from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) print("running cmd: " .. cmd_pipe_cmd) - ok, out, err = run_with_cmd(cmd_pipe_cmd) + ok, out, err = os.iorun_in_shell("cmd", cmd_pipe_cmd) print("STDOUT 9:\n" .. (out or "")) print("STDERR 9:\n" .. (err or "")) assert(ok, "test 9 failed: command returned error") @@ -301,7 +191,7 @@ target("test") local cmd_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_scriptfile, win_xmake) print("running cmd: " .. cmd_file_cmd) - ok, out, err = run_with_cmd(cmd_file_cmd) + ok, out, err = os.iorun_in_shell("cmd", cmd_file_cmd) print("STDOUT 10:\n" .. (out or "")) print("STDERR 10:\n" .. (err or "")) assert(ok, "test 10 failed: command returned error") @@ -311,7 +201,7 @@ target("test") -- test 11: cmd pipe error (multiline) local cmd_err_pipe_cmd = string.format("(echo print\"ok step\" && echo raise\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) print("running cmd: " .. cmd_err_pipe_cmd) - ok, out, err = run_with_cmd(cmd_err_pipe_cmd) + ok, out, err = os.iorun_in_shell("cmd", cmd_err_pipe_cmd) print("STDOUT 11:\n" .. (out or "")) print("STDERR 11:\n" .. (err or "")) assert(not ok, "test 11 failed: command should have returned error") @@ -325,7 +215,7 @@ target("test") local cmd_err_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_errorfile, win_xmake) print("running cmd: " .. cmd_err_file_cmd) - ok, out, err = run_with_cmd(cmd_err_file_cmd) + ok, out, err = os.iorun_in_shell("cmd", cmd_err_file_cmd) print("STDOUT 12:\n" .. (out or "")) print("STDERR 12:\n" .. (err or "")) assert(not ok, "test 12 failed: command should have returned error") diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 9332f2c61..86f04e35d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1106,6 +1106,51 @@ function os.iorunv(program, argv, opt) return ok == 0, outdata, errdata, errors end +-- run command in the given shell and return output and error data +-- +-- @param shell the shell name (e.g. sh, bash, zsh, cmd, pwsh, powershell) +-- @param cmd the command string +-- @param opt the options +-- +-- @return ok, stdout, stderr, errors +-- +function os.iorun_in_shell(shell, cmd, opt) + + -- check + if not shell or not cmd then + return false, nil, nil, "invalid arguments" + end + + -- run in pwsh/powershell + if shell == "pwsh" or shell == "powershell" then + local shell_cmd = string.format("& { %s; exit $LASTEXITCODE }", cmd) + return os.iorunv(shell, {"-c", shell_cmd}, opt) + + -- run in cmd + elseif shell == "cmd" then + + -- use batfile to robust pipe handling + local batfile = os.tmpfile() .. ".bat" + local batch_content = "@echo off\n" + + -- append command + batch_content = batch_content .. cmd .. "\n" + + -- append exit code check + batch_content = batch_content .. "if %errorlevel% neq 0 exit /b %errorlevel%\n" + + io.writefile(batfile, batch_content) + + local ok, out, err, errors = os.iorunv(batfile, {}, opt) + os.rm(batfile) + return ok, out, err, errors + + -- run in sh/bash/zsh... + else + return os.iorunv(shell, {"-c", cmd}, opt) + end +end + -- raise an exception and abort the current script -- -- the parent function will capture it if we uses pcall or xpcall diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index aebb3cfb0..ec5cb0e1e 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -324,6 +324,12 @@ function sandbox_os.iorunv(program, argv, opt) return outdata, errdata end +-- run command in shell with io redirection and return (ok, out, err) +function sandbox_os.iorun_in_shell(shell, cmd, ...) + cmd = vformat(cmd, ...) + return os.iorun_in_shell(shell, cmd) +end + -- execute command function sandbox_os.exec(cmd, ...) cmd = vformat(cmd, ...) -- cgit v1.3.1 From 26904439b5907b973201019a5d1083eee1261272 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:39:02 +0300 Subject: refactor: enhance temporary file naming for stdin script handling --- xmake/plugins/lua/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index f3e6f400d..26cc8a360 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -63,7 +63,7 @@ function main() if script == "-" or from_stdin then local script_content = io.stdin:read("*a") if script_content then - scriptfile_stdin = os.tmpfile("xmake_lua_stdin") .. ".lua" + scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" io.writefile(scriptfile_stdin, script_content) if from_stdin and script and script ~= "-" then arguments = arguments or {} -- cgit v1.3.1 From a6c7c34b0a3cba1f95a3411232bc566c62a661d0 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:43:57 +0300 Subject: refactor: fix stdin script reading method for improved compatibility --- xmake/plugins/lua/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 26cc8a360..b6951c276 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -61,7 +61,7 @@ function main() -- run script from stdin? local scriptfile_stdin if script == "-" or from_stdin then - local script_content = io.stdin:read("*a") + local script_content = io.read("*a") if script_content then scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" io.writefile(scriptfile_stdin, script_content) -- cgit v1.3.1 From 09a702d482edc5fb7218900460442822e1303810 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:57:49 +0300 Subject: refactor: enhance script handling to support inline Lua content execution --- .../sandbox/modules/import/core/sandbox/module.lua | 69 +++++++++++++++++++--- xmake/modules/utils/run_script.lua | 7 ++- xmake/plugins/lua/main.lua | 49 +++++---------- 3 files changed, 80 insertions(+), 45 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index dd7dac16e..3c76da6ff 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -67,6 +67,41 @@ function core_sandbox_module._modulepath(name) return modulepath end +-- load module from string +function core_sandbox_module._loadstring(content, instance, name) + assert(content) + + -- load module script + local script, errors = load(content, name) + if not script then + return nil, errors + end + + -- with sandbox? + if instance then + + -- fork a new sandbox for this script + instance, errors = instance:fork(script, instance:rootdir()) + if not instance then + return nil, errors + end + + -- load module + local result, errors = instance:module() + if not result then + return nil, errors + end + return result, instance:script() + end + + -- load module without sandbox + local ok, result = utils.trycall(script) + if not ok then + return nil, result + end + return result, script +end + -- load module from file function core_sandbox_module._loadfile(filepath, instance) assert(filepath) @@ -510,21 +545,37 @@ function core_sandbox_module.import(name, opt) local instance = sandbox.instance() assert(instance) - -- the root directory for this sandbox script + -- rootdir is optional local rootdir = opt.rootdir or instance:rootdir() - -- init module directories (disable local packages?) - local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) + -- load module from content? + local module + local errors + local found = false + if opt.content then + found = true + module, errors = core_sandbox_module._loadstring(opt.content, instance, name) + if module then + if not opt.nocache then + modules[name] = {module, nil} + end + end + else - -- load module - local loadopt = table.clone(opt) or {} - loadopt.instance = instance - loadopt.modules = modules - loadopt.modules_directories = modules_directories - local found, module, errors = core_sandbox_module._find_and_load(name, loadopt) + -- init module directories (disable local packages?) + local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) + -- load module + local loadopt = table.clone(opt) or {} + loadopt.instance = instance + loadopt.modules = modules + loadopt.modules_directories = modules_directories + found, module, errors = core_sandbox_module._find_and_load(name, loadopt) + end + -- not found? attempt to load module.interface if not found and not opt.inherit then + -- get module name local found2 = false local errors2 = nil diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index e6f8469f6..a51f4eef0 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -61,7 +61,12 @@ function _run_script(script, args, opt) local script_type, script_name -- import and run script - if path.extension(script) == ".lua" and os.isfile(script) then + if opt.content then + + -- run the given lua script content + script_type, script_name = "given lua script content", script + func = import(script, {anonymous = true, content = opt.content}) + elseif path.extension(script) == ".lua" and os.isfile(script) then -- run the given lua script file (xmake lua /tmp/script.lua) script_type, script_name = "given lua script file", path.relative(script) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index b6951c276..0a608b10a 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -59,45 +59,24 @@ function main() if script or from_stdin then -- run script from stdin? - local scriptfile_stdin + local script_content if script == "-" or from_stdin then - local script_content = io.read("*a") - if script_content then - scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" - io.writefile(scriptfile_stdin, script_content) - if from_stdin and script and script ~= "-" then - arguments = arguments or {} - table.insert(arguments, 1, script) - end - script = scriptfile_stdin + script_content = io.read("*a") + if not script or script == "-" then + script = "xmake_lua_stdin" end end - try { - function () - if script then - run_script(script, { - curdir = os.workingdir(), - verbose = option.get("verbose"), - diagnosis = option.get("diagnosis"), - command = option.get("command"), - arguments = arguments, - deserialize = option.get("deserialize")}) - end - end, - catch { - function (errors) - raise(errors) - end - }, - finally { - function () - if scriptfile_stdin then - os.rm(scriptfile_stdin) - end - end - } - } + if script then + run_script(script, { + curdir = os.workingdir(), + verbose = option.get("verbose"), + diagnosis = option.get("diagnosis"), + command = option.get("command"), + arguments = arguments, + content = script_content, + deserialize = option.get("deserialize")}) + end else -- enter interactive mode sandbox.interactive() -- cgit v1.3.1 From 336fce6edf7a4a2932b8ac0881cd10b2d62d3ecc Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 09:03:14 +0300 Subject: refactor: streamline module import logic by consolidating directory initialization --- .../sandbox/modules/import/core/sandbox/module.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index 3c76da6ff..34d55415d 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -548,7 +548,16 @@ function core_sandbox_module.import(name, opt) -- rootdir is optional local rootdir = opt.rootdir or instance:rootdir() - -- load module from content? + -- init module directories (disable local packages?) + local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) + + -- load module + local loadopt = table.clone(opt) or {} + loadopt.instance = instance + loadopt.modules = modules + loadopt.modules_directories = modules_directories + + -- load module local module local errors local found = false @@ -561,15 +570,6 @@ function core_sandbox_module.import(name, opt) end end else - - -- init module directories (disable local packages?) - local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) - - -- load module - local loadopt = table.clone(opt) or {} - loadopt.instance = instance - loadopt.modules = modules - loadopt.modules_directories = modules_directories found, module, errors = core_sandbox_module._find_and_load(name, loadopt) end -- cgit v1.3.1 From 554f7a23f12ba4df73c23de64d52855e82a37088 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:06:52 +0300 Subject: refactor: improve stdin handling and shell command execution across platforms --- tests/modules/stdin/test.lua | 75 +++++++ tests/projects/test_stdin/xmake.lua | 226 --------------------- xmake/core/base/os.lua | 50 +---- .../sandbox/modules/import/core/sandbox/module.lua | 55 +---- xmake/core/sandbox/modules/os.lua | 6 - xmake/modules/utils/run_script.lua | 7 +- xmake/plugins/lua/main.lua | 26 ++- xmake/plugins/lua/xmake.lua | 20 +- 8 files changed, 109 insertions(+), 356 deletions(-) create mode 100644 tests/modules/stdin/test.lua delete mode 100644 tests/projects/test_stdin/xmake.lua diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua new file mode 100644 index 000000000..72551ed9c --- /dev/null +++ b/tests/modules/stdin/test.lua @@ -0,0 +1,75 @@ +target("test") + set_kind("phony") + on_run(function (target) + local xmake = path.unix(os.programfile()) + if os.host() == "windows" then + xmake = xmake:gsub("/", "\\") + end + + local function test_shell(name, cmd, expect) + print("testing " .. name .. ": " .. cmd) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format("%s > \"%s\" 2> \"%s\"", cmd, outfile, errfile) + local ret = -1 + try { + function () + if os.host() ~= "windows" then + ret = os.execv("sh", {"-c", full_cmd}) + else + ret = os.exec(full_cmd) + end + end + } + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + if out:find(expect) then + print(" -> passed") + else + print(" -> failed") + raise("[test_stdin]: Test failed! Expect: ", expect) + end + print(" out: " .. (out or "")) + print(" err: " .. (err or "")) + os.tryrm(outfile) + os.tryrm(errfile) + end + + local pwsh = "" + if os.host() == "windows" then + -- Test cmd + test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") + test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") + -- Test powershell (if available) + local pwsh = "powershell" + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + else + -- Linux/MacOS + local pwsh = "" + try { function () os.iorun("pwsh -v"); pwsh = "pwsh" end } + if pwsh == "" then + try { function () os.iorun("powershell -v"); pwsh = "powershell" end } + end + + if pwsh ~= "" then + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + end + + test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") + test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") + end + end) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua deleted file mode 100644 index a603a08e9..000000000 --- a/tests/projects/test_stdin/xmake.lua +++ /dev/null @@ -1,226 +0,0 @@ -target("test") - set_kind("phony") - on_run(function (target) - import("core.base.option") - local xmake = path.unix(os.programfile()) - local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") - print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) - print("xmake binary: " .. xmake) - - if xmake_dir then - xmake_dir = path.unix(xmake_dir) - if os.host() == "windows" then - xmake_dir = xmake_dir:gsub("/", "\\") - end - os.setenv("XMAKE_PROGRAM_DIR", xmake_dir) - end - - -- New Helper: Probe for feature working (handles Windows/pwsh fallback) - local function check_feature() - print("Checking feature: --from-stdin ...") - local shell = os.shell() - - -- 1. Try detected shell if compatible - if shell == "pwsh" or shell == "powershell" then - local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell(shell, pwsh_probe) - if ok and out and out:find("probe_ok") then return true end - elseif shell == "cmd" then - local win_xmake = xmake:gsub("/", "\\") - local cmd_probe = string.format("echo print\"probe_ok\" | \"%s\" lua --from-stdin", win_xmake) - local ok, out, _ = os.iorun_in_shell("cmd", cmd_probe) - if ok and out and out:find("probe_ok") then return true end - end - - -- 2. Try generic sh (preferred if available validation default) - local probe_cmd = string.format("echo 'print(\"probe_ok\")' | %s lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell("sh", probe_cmd) - if ok and out and out:find("probe_ok") then return true end - - -- 3. Fallback: On Windows, try pwsh if sh failed - if os.host() == "windows" and shell ~= "pwsh" and shell ~= "powershell" and shell ~= "cmd" then - local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell("pwsh", pwsh_probe) - if ok and out and out:find("probe_ok") then return true end - end - return false - end - - -- check if feature is present - if check_feature() then - print("Feature presence check: PASS") - else - local ok, out, err = os.iorun_in_shell("sh", string.format("%s lua --help", xmake)) - if out and out:find("--from-stdin", 1, true) then - print("Feature presence check: PASS (via help text)") - else - print("Feature presence check: FAIL") - print("Help output (snippet): " .. (out and out:sub(1,100) or "nil")) - end - end - - -- test 1: pipe a few lines of lua code from echo (multiline) - local pipe_cmd = string.format("(echo 'print(\"hello\")'; echo 'print(\"from pipe\")') | '%s' lua --from-stdin", xmake) - print("running: " .. pipe_cmd) - local ok, out, err = os.iorun_in_shell("sh", pipe_cmd) - print("STDOUT 1:\n" .. (out or "")) - print("STDERR 1:\n" .. (err or "")) - assert(ok, "test 1 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pipe"), "test 1 failed: output mismatch") - end - - -- test 2: redirect from a .lua file (multiline) - -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging on Win - local scriptfile = path.join(os.curdir(), "test.lua") - io.writefile(scriptfile, 'print("hello")\nprint("from file")\n') - - local cat_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(scriptfile), xmake) - print("running: " .. cat_cmd) - ok, out, err = os.iorun_in_shell("sh", cat_cmd) - print("STDOUT 2:\n" .. (out or "")) - print("STDERR 2:\n" .. (err or "")) - - assert(ok, "test 2 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from file"), "test 2 failed: output mismatch") - end - os.rm(scriptfile) - - -- test 3: verify traceback on error via pipe (multiline) - local error_pipe_cmd = string.format("(echo 'print(\"ok step\")'; echo 'raise(\"error_pipe\")') | '%s' lua --from-stdin", xmake) - print("running: " .. error_pipe_cmd) - ok, out, err = os.iorun_in_shell("sh", error_pipe_cmd) - print("STDOUT 3:\n" .. (out or "")) - print("STDERR 3:\n" .. (err or "")) - assert(not ok, "test 3 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 3 failed: missing ok step output") end - assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - - -- test 4: verify traceback on error via file (multiline) - local errorfile = path.join(os.curdir(), "error.lua") - io.writefile(errorfile, 'print("ok step")\nraise("error_file")\n') - - -- FIX: Use cat and merge stderr (2>&1) - local error_file_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(errorfile), xmake) - print("running: " .. error_file_cmd) - ok, out, err = os.iorun_in_shell("sh", error_file_cmd) - print("STDOUT 4:\n" .. (out or "")) - print("STDERR 4:\n" .. (err or "")) - - assert(not ok, "test 4 failed: command should have returned error") - -- Check out (merged) or err just in case - if out then assert(out:find("ok step"), "test 4 failed: missing ok step output") end - assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") - os.rm(errorfile) - - -- pwsh tests - if os.execv("pwsh", {"-v"}) == 0 then - print("pwsh detected, running pwsh tests...") - - -- test 5: pwsh pipe success (multiline) - local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello`\")`nprint(`\"from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) - print("running pwsh: " .. pwsh_pipe_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_pipe_cmd) - print("STDOUT 5:\n" .. (out or "")) - print("STDERR 5:\n" .. (err or "")) - assert(ok, "test 5 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pwsh pipe"), "test 5 failed: output mismatch") - end - - -- test 6: pwsh file redirect success (multiline) - local scriptfile = path.join(os.curdir(), "test_pwsh.lua") - io.writefile(scriptfile, 'print("hello")\nprint("from pwsh file")\n') - local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) - print("running pwsh: " .. pwsh_redirect_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_redirect_cmd) - print("STDOUT 6:\n" .. (out or "")) - print("STDERR 6:\n" .. (err or "")) - assert(ok, "test 6 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pwsh file"), "test 6 failed: output mismatch") - end - os.rm(scriptfile) - - -- test 7: pwsh pipe error (multiline) - local pwsh_error_pipe_cmd = string.format("Write-Output \"print(`\"ok step`\")`nraise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) - print("running pwsh: " .. pwsh_error_pipe_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_pipe_cmd) - print("STDOUT 7:\n" .. (out or "")) - print("STDERR 7:\n" .. (err or "")) - assert(not ok, "test 7 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 7 failed: missing ok step output") end - assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") - - -- test 8: pwsh file redirect error (multiline) - local errorfile = path.join(os.curdir(), "error_pwsh.lua") - io.writefile(errorfile, 'print("ok step")\nraise("error_pwsh_file")\n') - local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) - print("running pwsh: " .. pwsh_error_file_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_file_cmd) - print("STDOUT 8:\n" .. (out or "")) - print("STDERR 8:\n" .. (err or "")) - assert(not ok, "test 8 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 8 failed: missing ok step output") end - assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") - os.rm(errorfile) - else - print("pwsh not found, skipping pwsh tests") - end - - -- cmd tests - if os.host() == "windows" then - print("windows detected, running cmd.exe tests...") - local win_xmake = xmake:gsub("/", "\\") - - -- test 9: cmd pipe success (multiline) - local cmd_pipe_cmd = string.format("(echo print\"hello\" && echo print\"from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) - print("running cmd: " .. cmd_pipe_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_pipe_cmd) - print("STDOUT 9:\n" .. (out or "")) - print("STDERR 9:\n" .. (err or "")) - assert(ok, "test 9 failed: command returned error") - if out then assert(out:find("hello") and out:find("from cmd pipe"), "test 9 failed: output mismatch") end - - -- test 10: cmd file pipe success (multiline) - local scriptfile = path.join(os.curdir(), "test_cmd.lua") - local win_scriptfile = scriptfile:gsub("/", "\\") - -- FIX: Add newline for robust 'type' piping - io.writefile(scriptfile, 'print("hello")\nprint("from cmd file")\n') - - local cmd_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_scriptfile, win_xmake) - print("running cmd: " .. cmd_file_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_file_cmd) - print("STDOUT 10:\n" .. (out or "")) - print("STDERR 10:\n" .. (err or "")) - assert(ok, "test 10 failed: command returned error") - if out then assert(out:find("hello") and out:find("from cmd file"), "test 10 failed: output mismatch") end - os.rm(scriptfile) - - -- test 11: cmd pipe error (multiline) - local cmd_err_pipe_cmd = string.format("(echo print\"ok step\" && echo raise\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) - print("running cmd: " .. cmd_err_pipe_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_err_pipe_cmd) - print("STDOUT 11:\n" .. (out or "")) - print("STDERR 11:\n" .. (err or "")) - assert(not ok, "test 11 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 11 failed: missing ok step output") end - assert((err and err:find("error_cmd_pipe")) or (out and out:find("error_cmd_pipe")), "test 11 failed: missing error message") - - -- test 12: cmd file pipe error (multiline) - local errorfile = path.join(os.curdir(), "error_cmd.lua") - local win_errorfile = errorfile:gsub("/", "\\") - io.writefile(errorfile, 'print("ok step")\nraise("error_cmd_file")\n') - - local cmd_err_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_errorfile, win_xmake) - print("running cmd: " .. cmd_err_file_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_err_file_cmd) - print("STDOUT 12:\n" .. (out or "")) - print("STDERR 12:\n" .. (err or "")) - assert(not ok, "test 12 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 12 failed: missing ok step output") end - assert((err and err:find("error_cmd_file")) or (out and out:find("error_cmd_file")), "test 12 failed: missing error message") - os.rm(errorfile) - end - end) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 86f04e35d..12bc30c1d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1106,51 +1106,6 @@ function os.iorunv(program, argv, opt) return ok == 0, outdata, errdata, errors end --- run command in the given shell and return output and error data --- --- @param shell the shell name (e.g. sh, bash, zsh, cmd, pwsh, powershell) --- @param cmd the command string --- @param opt the options --- --- @return ok, stdout, stderr, errors --- -function os.iorun_in_shell(shell, cmd, opt) - - -- check - if not shell or not cmd then - return false, nil, nil, "invalid arguments" - end - - -- run in pwsh/powershell - if shell == "pwsh" or shell == "powershell" then - local shell_cmd = string.format("& { %s; exit $LASTEXITCODE }", cmd) - return os.iorunv(shell, {"-c", shell_cmd}, opt) - - -- run in cmd - elseif shell == "cmd" then - - -- use batfile to robust pipe handling - local batfile = os.tmpfile() .. ".bat" - local batch_content = "@echo off\n" - - -- append command - batch_content = batch_content .. cmd .. "\n" - - -- append exit code check - batch_content = batch_content .. "if %errorlevel% neq 0 exit /b %errorlevel%\n" - - io.writefile(batfile, batch_content) - - local ok, out, err, errors = os.iorunv(batfile, {}, opt) - os.rm(batfile) - return ok, out, err, errors - - -- run in sh/bash/zsh... - else - return os.iorunv(shell, {"-c", cmd}, opt) - end -end - -- raise an exception and abort the current script -- -- the parent function will capture it if we uses pcall or xpcall @@ -1232,10 +1187,7 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - if os._access then - return os._access(filepath, "x") - end - return true + return os._access(filepath, "x") end return false end diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index 34d55415d..dd7dac16e 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -67,41 +67,6 @@ function core_sandbox_module._modulepath(name) return modulepath end --- load module from string -function core_sandbox_module._loadstring(content, instance, name) - assert(content) - - -- load module script - local script, errors = load(content, name) - if not script then - return nil, errors - end - - -- with sandbox? - if instance then - - -- fork a new sandbox for this script - instance, errors = instance:fork(script, instance:rootdir()) - if not instance then - return nil, errors - end - - -- load module - local result, errors = instance:module() - if not result then - return nil, errors - end - return result, instance:script() - end - - -- load module without sandbox - local ok, result = utils.trycall(script) - if not ok then - return nil, result - end - return result, script -end - -- load module from file function core_sandbox_module._loadfile(filepath, instance) assert(filepath) @@ -545,7 +510,7 @@ function core_sandbox_module.import(name, opt) local instance = sandbox.instance() assert(instance) - -- rootdir is optional + -- the root directory for this sandbox script local rootdir = opt.rootdir or instance:rootdir() -- init module directories (disable local packages?) @@ -556,26 +521,10 @@ function core_sandbox_module.import(name, opt) loadopt.instance = instance loadopt.modules = modules loadopt.modules_directories = modules_directories + local found, module, errors = core_sandbox_module._find_and_load(name, loadopt) - -- load module - local module - local errors - local found = false - if opt.content then - found = true - module, errors = core_sandbox_module._loadstring(opt.content, instance, name) - if module then - if not opt.nocache then - modules[name] = {module, nil} - end - end - else - found, module, errors = core_sandbox_module._find_and_load(name, loadopt) - end - -- not found? attempt to load module.interface if not found and not opt.inherit then - -- get module name local found2 = false local errors2 = nil diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index ec5cb0e1e..aebb3cfb0 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -324,12 +324,6 @@ function sandbox_os.iorunv(program, argv, opt) return outdata, errdata end --- run command in shell with io redirection and return (ok, out, err) -function sandbox_os.iorun_in_shell(shell, cmd, ...) - cmd = vformat(cmd, ...) - return os.iorun_in_shell(shell, cmd) -end - -- execute command function sandbox_os.exec(cmd, ...) cmd = vformat(cmd, ...) diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index a51f4eef0..e6f8469f6 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -61,12 +61,7 @@ function _run_script(script, args, opt) local script_type, script_name -- import and run script - if opt.content then - - -- run the given lua script content - script_type, script_name = "given lua script content", script - func = import(script, {anonymous = true, content = opt.content}) - elseif path.extension(script) == ".lua" and os.isfile(script) then + if path.extension(script) == ".lua" and os.isfile(script) then -- run the given lua script file (xmake lua /tmp/script.lua) script_type, script_name = "given lua script file", path.relative(script) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 0a608b10a..a945a64c1 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -55,15 +55,26 @@ function main() -- run script local script = option.get("script") local arguments = option.get("arguments") - local from_stdin = option.get("from_stdin") or option.get("from-stdin") + local from_stdin = option.get("stdin") if script or from_stdin then -- run script from stdin? - local script_content + local script_file_to_remove if script == "-" or from_stdin then - script_content = io.read("*a") - if not script or script == "-" then - script = "xmake_lua_stdin" + local script_content = io.read("*a") + if script_content then + import("core.base.tty") + local shell = tty.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then + script_content = script_content:trim() + if script_content:startswith('"') and script_content:endswith('"') then + script_content = script_content:sub(2, -2) + end + script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + end + script = os.tmpfile() .. ".lua" + io.writefile(script, script_content) + script_file_to_remove = script end end @@ -74,8 +85,11 @@ function main() diagnosis = option.get("diagnosis"), command = option.get("command"), arguments = arguments, - content = script_content, deserialize = option.get("deserialize")}) + + if script_file_to_remove then + os.tryrm(script_file_to_remove) + end end else -- enter interactive mode diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 467cde3f1..8b60c96d3 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -45,20 +45,20 @@ task("lua") {'l', "list" , "k" , nil , "List all scripts." } , {'c', "command" , "k" , nil , "Run script as command" } , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } - , {nil, "from-stdin" , "k" , nil , "Run script from stdin", + , {nil, "stdin" , "k" , nil , "Run script from stdin", "e.g.", " - CMD", - " - Single: echo print(\"hello\") | xmake lua --from-stdin", - " - Multiline: (echo print('1') && echo print('2')) | xmake lua --from-stdin", - " - File: type script.lua | xmake lua --from-stdin", + " - Single: echo print(\"hello\") | xmake lua --stdin", + " - Multiline: (echo print('1') && echo print('2')) | xmake lua --stdin", + " - File: type script.lua | xmake lua --stdin", " - PWSH", - " - Single: Write-Output 'print(\"hello\")' | xmake lua --from-stdin", - " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --from-stdin", - " - File: Get-Content script.lua | xmake lua --from-stdin", + " - Single: Write-Output 'print(\"hello\")' | xmake lua --stdin", + " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --stdin", + " - File: Get-Content script.lua | xmake lua --stdin", " - SH", - " - Single: echo 'print(\"hello\")' | xmake lua --from-stdin", - " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --from-stdin", - " - File: cat script.lua | xmake lua --from-stdin" + " - Single: echo 'print(\"hello\")' | xmake lua --stdin", + " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --stdin", + " - File: cat script.lua | xmake lua --stdin" } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", -- cgit v1.3.1 From 5313286703675d51f54cde0a8d0ea382619ae84c Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:20:33 +0300 Subject: refactor: restructure test function and improve output handling --- tests/modules/stdin/test.lua | 137 ++++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 68 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 72551ed9c..c58e0705d 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,75 +1,76 @@ -target("test") - set_kind("phony") - on_run(function (target) - local xmake = path.unix(os.programfile()) - if os.host() == "windows" then - xmake = xmake:gsub("/", "\\") - end +function main(t) +local xmake = path.unix(os.programfile()) +if os.host() == "windows" then + xmake = xmake:gsub("/", "\\") +end - local function test_shell(name, cmd, expect) - print("testing " .. name .. ": " .. cmd) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local full_cmd = string.format("%s > \"%s\" 2> \"%s\"", cmd, outfile, errfile) - local ret = -1 - try { - function () - if os.host() ~= "windows" then - ret = os.execv("sh", {"-c", full_cmd}) - else - ret = os.exec(full_cmd) - end - end - } - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - if out and out:find("\0", 1, true) then - out = out:gsub("\0", "") - end - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - end - if out:find(expect) then - print(" -> passed") +local function test_shell(name, cmd, expect) + print("testing " .. name .. ": " .. cmd) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format("%s > \"%s\" 2> \"%s\"", cmd, outfile, errfile) + local ret = -1 + try { + function () + if os.host() ~= "windows" then + ret = os.execv("sh", {"-c", full_cmd}) else - print(" -> failed") - raise("[test_stdin]: Test failed! Expect: ", expect) + ret = os.exec(full_cmd) end - print(" out: " .. (out or "")) - print(" err: " .. (err or "")) - os.tryrm(outfile) - os.tryrm(errfile) end + } + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + local passed = out:find(expect) + if passed then + print(" -> passed") + else + print(" -> failed") + end + print(" out: " .. (out or "")) + print(" err: " .. (err or "")) + if not passed then + raise("[test_stdin]: Test failed! Expect: ", expect) + end + os.tryrm(outfile) + os.tryrm(errfile) +end - local pwsh = "" - if os.host() == "windows" then - -- Test cmd - test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") - test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") - -- Test powershell (if available) - local pwsh = "powershell" - if os.exec("pwsh -v") == 0 then - pwsh = "pwsh" - end - test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") - else - -- Linux/MacOS - local pwsh = "" - try { function () os.iorun("pwsh -v"); pwsh = "pwsh" end } - if pwsh == "" then - try { function () os.iorun("powershell -v"); pwsh = "powershell" end } - end +local pwsh = "" +if os.host() == "windows" then + -- Test cmd + test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") + test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") + -- Test powershell (if available) + local pwsh = "powershell" + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") +else + -- Linux/MacOS + local pwsh = "" + try { function () os.iorun("pwsh -v"); pwsh = "pwsh" end } + if pwsh == "" then + try { function () os.iorun("powershell -v"); pwsh = "powershell" end } + end - if pwsh ~= "" then - test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") - end + if pwsh ~= "" then + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + end - test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") - test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") - end - end) + test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") + test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") +end +end -- cgit v1.3.1 From 05dc5f8fbfd139cb9cbe1c6679b59aba9ae02dd4 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:25:14 +0300 Subject: refactor: wrap script content in a main function for better execution context --- xmake/plugins/lua/main.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index a945a64c1..0c0b44005 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -72,6 +72,7 @@ function main() end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end + script_content = "function main(...)\n" .. script_content .. "\nend" script = os.tmpfile() .. ".lua" io.writefile(script, script_content) script_file_to_remove = script -- cgit v1.3.1 From 2b7c02a0ef930e394829027fab3d7acaa948d6e9 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:31:00 +0300 Subject: refactor: add additional test cases for shell and powershell calculations --- tests/modules/stdin/test.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index c58e0705d..1cef7a362 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -49,6 +49,7 @@ local pwsh = "" if os.host() == "windows" then -- Test cmd test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") + test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") -- Test powershell (if available) local pwsh = "powershell" @@ -56,6 +57,7 @@ if os.host() == "windows" then pwsh = "pwsh" end test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") else -- Linux/MacOS @@ -67,10 +69,12 @@ else if pwsh ~= "" then test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") end test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") + test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") end end -- cgit v1.3.1 From 50b428269a657fd0adce1de35b01abe42c13708b Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:40:44 +0300 Subject: refactor: enhance stdin handling by adding utf8 BOM removal and main function check --- tests/modules/stdin/test.lua | 4 +++- xmake/plugins/lua/main.lua | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 1cef7a362..bcd9efca6 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -70,11 +70,13 @@ else if pwsh ~= "" then test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + test_shell("pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s l --stdin"', pwsh, xmake), "in_pwsh_main") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") end test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell("sh_main", string.format('echo "function main() print(\'in_sh_main\') end" | %s l --stdin', xmake), "in_sh_main") test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") end end diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 0c0b44005..1cc13dbc3 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -63,6 +63,10 @@ function main() if script == "-" or from_stdin then local script_content = io.read("*a") if script_content then + -- remove utf8 bom + if script_content:startswith("\239\187\191") then + script_content = script_content:sub(4) + end import("core.base.tty") local shell = tty.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then @@ -72,7 +76,11 @@ function main() end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end - script_content = "function main(...)\n" .. script_content .. "\nend" + + if not script_content:find("function main", 1, true) then + script_content = "function main(...)\n" .. script_content .. "\nend" + end + script = os.tmpfile() .. ".lua" io.writefile(script, script_content) script_file_to_remove = script -- cgit v1.3.1 From 0588ca91219e1ac614e234b7307941ec9b6df161 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 15:03:58 +0300 Subject: refactor: wrap PowerShell version check in a try block for improved error handling --- tests/modules/stdin/test.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index bcd9efca6..89e6e5a38 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -53,9 +53,11 @@ if os.host() == "windows" then test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") -- Test powershell (if available) local pwsh = "powershell" - if os.exec("pwsh -v") == 0 then - pwsh = "pwsh" - end + try { function () + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + end } test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") -- cgit v1.3.1 From 9d45443b6cf3a6bb2a0e0f6ab30347cb826c700d Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 16:03:52 +0300 Subject: stylua fmt? --- tests/modules/stdin/test.lua | 216 +++++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 78 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 89e6e5a38..bd4bb5964 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,84 +1,144 @@ function main(t) -local xmake = path.unix(os.programfile()) -if os.host() == "windows" then - xmake = xmake:gsub("/", "\\") -end + local xmake = path.unix(os.programfile()) + if os.host() == "windows" then + xmake = xmake:gsub("/", "\\") + end -local function test_shell(name, cmd, expect) - print("testing " .. name .. ": " .. cmd) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local full_cmd = string.format("%s > \"%s\" 2> \"%s\"", cmd, outfile, errfile) - local ret = -1 - try { - function () - if os.host() ~= "windows" then - ret = os.execv("sh", {"-c", full_cmd}) - else - ret = os.exec(full_cmd) - end - end - } - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - if out and out:find("\0", 1, true) then - out = out:gsub("\0", "") - end - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - end - local passed = out:find(expect) - if passed then - print(" -> passed") - else - print(" -> failed") - end - print(" out: " .. (out or "")) - print(" err: " .. (err or "")) - if not passed then - raise("[test_stdin]: Test failed! Expect: ", expect) - end - os.tryrm(outfile) - os.tryrm(errfile) -end + local function test_shell(name, cmd, expect) + print("testing " .. name .. ": " .. cmd) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) + local ret = -1 + try({ + function() + if os.host() ~= "windows" then + ret = os.execv("sh", { "-c", full_cmd }) + else + ret = os.exec(full_cmd) + end + end, + }) + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + local passed = out:find(expect) + if passed then + print(" -> passed") + else + print(" -> failed") + end + print(" out: " .. (out or "")) + print(" err: " .. (err or "")) + if not passed then + raise("[test_stdin]: Test failed! Expect: ", expect) + end + os.tryrm(outfile) + os.tryrm(errfile) + end -local pwsh = "" -if os.host() == "windows" then - -- Test cmd - test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") - test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") - -- Test powershell (if available) - local pwsh = "powershell" - try { function () - if os.exec("pwsh -v") == 0 then - pwsh = "pwsh" - end - end } - test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") - test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") -else - -- Linux/MacOS - local pwsh = "" - try { function () os.iorun("pwsh -v"); pwsh = "pwsh" end } - if pwsh == "" then - try { function () os.iorun("powershell -v"); pwsh = "powershell" end } - end + local pwsh = "" + if os.host() == "windows" then + -- Test cmd + test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") + test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell( + "cmd_multi", + string.format("cmd /c echo \"print('line1')\\nprint('line2')\" | %s l --stdin", xmake), + "line1[\r\n]+line2" + ) + -- Test powershell (if available) + local pwsh = "powershell" + try({ + function() + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + end, + }) + test_shell( + "pwsh_single", + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), + "hello_pwsh" + ) + test_shell( + "pwsh_calc", + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), + "2" + ) + test_shell( + "pwsh_multi", + string.format("%s -c \"echo \\\"print('pline1')\\nprint('pline2')\\\" | %s l --stdin\"", pwsh, xmake), + "pline1[\r\n]+pline2" + ) + else + -- Linux/MacOS + local pwsh = "" + try({ + function() + os.iorun("pwsh -v") + pwsh = "pwsh" + end, + }) + if pwsh == "" then + try({ + function() + os.iorun("powershell -v") + pwsh = "powershell" + end, + }) + end - if pwsh ~= "" then - test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") - test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") - test_shell("pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s l --stdin"', pwsh, xmake), "in_pwsh_main") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") - end + if pwsh ~= "" then + test_shell( + "pwsh_single", + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), + "hello_pwsh" + ) + test_shell( + "pwsh_calc", + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), + "2" + ) + test_shell( + "pwsh_main", + string.format( + '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s l --stdin"', + pwsh, + xmake + ), + "in_pwsh_main" + ) + test_shell( + "pwsh_multi", + string.format( + '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s l --stdin"', + pwsh, + xmake + ), + "pline1[\r\n]+pline2" + ) + end - test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") - test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - test_shell("sh_main", string.format('echo "function main() print(\'in_sh_main\') end" | %s l --stdin', xmake), "in_sh_main") - test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") -end + test_shell("sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") + test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell( + "sh_main", + string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), + "in_sh_main" + ) + test_shell( + "sh_multi", + string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), + "shell_line1[\r\n]+shell_line2" + ) + end end -- cgit v1.3.1 From faca264f8ea0fb695f6bc8b3a9d1411f901f054b Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 16:14:46 +0300 Subject: refactor: simplify stdin handling by removing redundant checks and streamlining usage examples --- xmake/plugins/lua/main.lua | 2 +- xmake/plugins/lua/xmake.lua | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 1cc13dbc3..247684e24 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -60,7 +60,7 @@ function main() -- run script from stdin? local script_file_to_remove - if script == "-" or from_stdin then + if from_stdin then local script_content = io.read("*a") if script_content then -- remove utf8 bom diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 8b60c96d3..bb9308378 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -47,18 +47,8 @@ task("lua") , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } , {nil, "stdin" , "k" , nil , "Run script from stdin", "e.g.", - " - CMD", - " - Single: echo print(\"hello\") | xmake lua --stdin", - " - Multiline: (echo print('1') && echo print('2')) | xmake lua --stdin", - " - File: type script.lua | xmake lua --stdin", - " - PWSH", - " - Single: Write-Output 'print(\"hello\")' | xmake lua --stdin", - " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --stdin", - " - File: Get-Content script.lua | xmake lua --stdin", - " - SH", - " - Single: echo 'print(\"hello\")' | xmake lua --stdin", - " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --stdin", - " - File: cat script.lua | xmake lua --stdin" + " - echo 'print(\"hello\")' | xmake lua --stdin", + " - cat script.lua | xmake lua --stdin" } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", -- cgit v1.3.1 From 0e07b14891d27765bfcabf071f102f6758db6666 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 16:36:56 +0300 Subject: refactor: update PowerShell test commands to use sh for stdin execution --- tests/modules/stdin/test.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index bd4bb5964..96d166591 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -100,18 +100,18 @@ function main(t) if pwsh ~= "" then test_shell( "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake), "hello_pwsh" ) test_shell( "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake), "2" ) test_shell( "pwsh_main", string.format( - '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s l --stdin"', + '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake ), @@ -120,7 +120,7 @@ function main(t) test_shell( "pwsh_multi", string.format( - '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s l --stdin"', + '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake ), -- cgit v1.3.1 From e2b38bd5e164e6584aceb6318556b0d2a1f08875 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 17:07:53 +0300 Subject: refactor: update PowerShell test commands to use a unified run_stdin format. Maybe would work with APE file format? --- tests/modules/stdin/test.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 96d166591..bf51a5cd2 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -98,31 +98,32 @@ function main(t) end if pwsh ~= "" then + local run_stdin = string.format('env "%s" l --stdin', xmake) test_shell( "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake), + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), "hello_pwsh" ) test_shell( "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | sh -c \\"%s l --stdin\\""', pwsh, xmake), + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), "2" ) test_shell( "pwsh_main", string.format( - '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | sh -c \\"%s l --stdin\\""', + '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, - xmake + run_stdin ), "in_pwsh_main" ) test_shell( "pwsh_multi", string.format( - '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | sh -c \\"%s l --stdin\\""', + '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, - xmake + run_stdin ), "pline1[\r\n]+pline2" ) -- cgit v1.3.1 From 74a37990201fa351fc433ff3cc2d698eeb9846c4 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 17:36:59 +0300 Subject: refactor: update PowerShell stdin command format for macOS compatibility --- tests/modules/stdin/test.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index bf51a5cd2..d942b7858 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -98,7 +98,10 @@ function main(t) end if pwsh ~= "" then - local run_stdin = string.format('env "%s" l --stdin', xmake) + local run_stdin = string.format("%s l --stdin", xmake) + if os.host() == "macosx" then + run_stdin = string.format('sh -c \\"%s\\"', run_stdin) + end test_shell( "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), -- cgit v1.3.1 From 1056c09cb31f7e873573d4e0a5a24d06af8297df Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 18:15:24 +0300 Subject: refactor: enhance APE/Cosmocc workaround by creating a temporary xmake alias for compatibility --- tests/modules/stdin/test.lua | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index d942b7858..162b58d53 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -4,6 +4,20 @@ function main(t) xmake = xmake:gsub("/", "\\") end + -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) + local function setup_xmake_alias(xmake) + if path.filename(xmake):find("ape-", 1, true) then + local xmake_dir = path.join(os.tmpdir(), "xmake_ape_" .. os.time()) + os.mkdir(xmake_dir) + local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") + os.trycp(xmake, xmake_alias) + return xmake_alias + end + return xmake + end + + xmake = setup_xmake_alias(xmake) + local function test_shell(name, cmd, expect) print("testing " .. name .. ": " .. cmd) local outfile = os.tmpfile() @@ -114,20 +128,12 @@ function main(t) ) test_shell( "pwsh_main", - string.format( - '%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', - pwsh, - run_stdin - ), + string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), "in_pwsh_main" ) test_shell( "pwsh_multi", - string.format( - '%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', - pwsh, - run_stdin - ), + string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" ) end -- cgit v1.3.1 From 00343d9994967c9f83a742bb049bd1fea450c887 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 18:51:05 +0300 Subject: refactor: ensure executable permissions for xmake alias on non-Windows platforms --- tests/modules/stdin/test.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 162b58d53..e0ebe7760 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -11,6 +11,9 @@ function main(t) os.mkdir(xmake_dir) local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") os.trycp(xmake, xmake_alias) + if os.host() ~= "windows" then + os.exec("chmod +x " .. xmake_alias) + end return xmake_alias end return xmake -- cgit v1.3.1 From 2fbded813d6b413f3174c85cf5ca4e6ec76dda28 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 18:54:23 +0300 Subject: refactor: standardize indentation and formatting in stdin test script --- tests/modules/stdin/test.lua | 295 +++++++++++++++++++++---------------------- 1 file changed, 146 insertions(+), 149 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index e0ebe7760..f2609c531 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,157 +1,154 @@ function main(t) - local xmake = path.unix(os.programfile()) - if os.host() == "windows" then - xmake = xmake:gsub("/", "\\") - end + local xmake = path.unix(os.programfile()) + if os.host() == "windows" then + xmake = xmake:gsub("/", "\\") + end - -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) - local function setup_xmake_alias(xmake) - if path.filename(xmake):find("ape-", 1, true) then - local xmake_dir = path.join(os.tmpdir(), "xmake_ape_" .. os.time()) - os.mkdir(xmake_dir) - local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") - os.trycp(xmake, xmake_alias) - if os.host() ~= "windows" then - os.exec("chmod +x " .. xmake_alias) - end - return xmake_alias - end - return xmake - end + -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) + local function setup_xmake_alias(xmake) + if path.filename(xmake):find("ape-", 1, true) then + local xmake_dir = path.join(os.tmpdir(), "xmake_ape_" .. os.time()) + os.mkdir(xmake_dir) + local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") + os.trycp(xmake, xmake_alias) + if os.host() ~= "windows" then + os.exec("chmod +x " .. xmake_alias) + end + return xmake_alias + end + return xmake + end - xmake = setup_xmake_alias(xmake) + xmake = setup_xmake_alias(xmake) - local function test_shell(name, cmd, expect) - print("testing " .. name .. ": " .. cmd) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) - local ret = -1 - try({ - function() - if os.host() ~= "windows" then - ret = os.execv("sh", { "-c", full_cmd }) - else - ret = os.exec(full_cmd) - end - end, - }) - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - if out and out:find("\0", 1, true) then - out = out:gsub("\0", "") - end - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - end - local passed = out:find(expect) - if passed then - print(" -> passed") - else - print(" -> failed") - end - print(" out: " .. (out or "")) - print(" err: " .. (err or "")) - if not passed then - raise("[test_stdin]: Test failed! Expect: ", expect) - end - os.tryrm(outfile) - os.tryrm(errfile) - end + local function test_shell(name, cmd, expect) + print("testing " .. name .. ": " .. cmd) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) + local ret = -1 + try({ + function() + if os.host() ~= "windows" then + ret = os.execv("sh", { "-c", full_cmd }) + else + ret = os.exec(full_cmd) + end + end, + }) + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + local passed = out:find(expect) + if passed then + print(" -> passed") + else + print(" -> failed") + end + print(" out: " .. (out or "")) + print(" err: " .. (err or "")) + if not passed then + raise("[test_stdin]: Test failed! Expect: ", expect) + end + os.tryrm(outfile) + os.tryrm(errfile) + end - local pwsh = "" - if os.host() == "windows" then - -- Test cmd - test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") - test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - test_shell( - "cmd_multi", - string.format("cmd /c echo \"print('line1')\\nprint('line2')\" | %s l --stdin", xmake), - "line1[\r\n]+line2" - ) - -- Test powershell (if available) - local pwsh = "powershell" - try({ - function() - if os.exec("pwsh -v") == 0 then - pwsh = "pwsh" - end - end, - }) - test_shell( - "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), - "hello_pwsh" - ) - test_shell( - "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), - "2" - ) - test_shell( - "pwsh_multi", - string.format("%s -c \"echo \\\"print('pline1')\\nprint('pline2')\\\" | %s l --stdin\"", pwsh, xmake), - "pline1[\r\n]+pline2" - ) - else - -- Linux/MacOS - local pwsh = "" - try({ - function() - os.iorun("pwsh -v") - pwsh = "pwsh" - end, - }) - if pwsh == "" then - try({ - function() - os.iorun("powershell -v") - pwsh = "powershell" - end, - }) - end + local pwsh = "" + if os.host() == "windows" then + -- Test cmd + test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") + test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell( + "cmd_multi", + string.format("cmd /c echo \"print('line1')\\nprint('line2')\" | %s l --stdin", xmake), + "line1[\r\n]+line2" + ) + -- Test powershell (if available) + local pwsh = "powershell" + try({ + function() + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + end, + }) + test_shell( + "pwsh_single", + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), + "hello_pwsh" + ) + test_shell( + "pwsh_calc", + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), + "2" + ) + test_shell( + "pwsh_multi", + string.format("%s -c \"echo \\\"print('pline1')\\nprint('pline2')\\\" | %s l --stdin\"", pwsh, xmake), + "pline1[\r\n]+pline2" + ) + else + -- Linux/MacOS + local pwsh = "" + try({ + function() + os.iorun("pwsh -v") + pwsh = "pwsh" + end, + }) + if pwsh == "" then + try({ + function() + os.iorun("powershell -v") + pwsh = "powershell" + end, + }) + end - if pwsh ~= "" then - local run_stdin = string.format("%s l --stdin", xmake) - if os.host() == "macosx" then - run_stdin = string.format('sh -c \\"%s\\"', run_stdin) - end - test_shell( - "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), - "hello_pwsh" - ) - test_shell( - "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), - "2" - ) - test_shell( - "pwsh_main", - string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), - "in_pwsh_main" - ) - test_shell( - "pwsh_multi", - string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), - "pline1[\r\n]+pline2" - ) - end + if pwsh ~= "" then + local run_stdin = string.format("%s l --stdin", xmake) + test_shell( + "pwsh_single", + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), + "hello_pwsh" + ) + test_shell( + "pwsh_calc", + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), + "2" + ) + test_shell( + "pwsh_main", + string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), + "in_pwsh_main" + ) + test_shell( + "pwsh_multi", + string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), + "pline1[\r\n]+pline2" + ) + end - test_shell("sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") - test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - test_shell( - "sh_main", - string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), - "in_sh_main" - ) - test_shell( - "sh_multi", - string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), - "shell_line1[\r\n]+shell_line2" - ) - end + test_shell("sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") + test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell( + "sh_main", + string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), + "in_sh_main" + ) + test_shell( + "sh_multi", + string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), + "shell_line1[\r\n]+shell_line2" + ) + end end -- cgit v1.3.1 From c68524a15b90a0c400930c9ca9c4ba4e7911e569 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 19:28:23 +0300 Subject: refactor: update PowerShell stdin command format for macOS compatibility --- tests/modules/stdin/test.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index f2609c531..44d0da2b7 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -116,6 +116,9 @@ function main(t) if pwsh ~= "" then local run_stdin = string.format("%s l --stdin", xmake) + if os.host() == "macosx" then + run_stdin = string.format('sh -c \\"%s\\"', run_stdin) + end test_shell( "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), -- cgit v1.3.1 From c6f69e8df34f2adc620a82036dda48a82fbd15bb Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 20:42:34 +0300 Subject: refactor: rename temporary xmake directory and update copy command for alias setup --- tests/modules/stdin/test.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 44d0da2b7..44521d6ad 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -7,10 +7,10 @@ function main(t) -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) local function setup_xmake_alias(xmake) if path.filename(xmake):find("ape-", 1, true) then - local xmake_dir = path.join(os.tmpdir(), "xmake_ape_" .. os.time()) + local xmake_dir = path.join(os.tmpdir(), "xm_alias_" .. os.time()) os.mkdir(xmake_dir) local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") - os.trycp(xmake, xmake_alias) + os.cp(xmake, xmake_alias) if os.host() ~= "windows" then os.exec("chmod +x " .. xmake_alias) end @@ -19,8 +19,17 @@ function main(t) return xmake end + local is_ape = path.filename(xmake):find("ape-", 1, true) + + -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = setup_xmake_alias(xmake) + local run_stdin = string.format('env "%s" l --stdin', xmake) + -- Fix pwsh and cosmocc "exec format error" for MacOS + if is_ape and os.host() == "macosx" then + run_stdin = string.format('sh -c \\"%s\\"', run_stdin) + end + local function test_shell(name, cmd, expect) print("testing " .. name .. ": " .. cmd) local outfile = os.tmpfile() @@ -115,10 +124,6 @@ function main(t) end if pwsh ~= "" then - local run_stdin = string.format("%s l --stdin", xmake) - if os.host() == "macosx" then - run_stdin = string.format('sh -c \\"%s\\"', run_stdin) - end test_shell( "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), -- cgit v1.3.1 From d155d5d080335d5932c4b65d2c713814ea28c00d Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 21:38:14 +0300 Subject: refactor: update stdin command format for Linux compatibility --- tests/modules/stdin/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 44521d6ad..461e76d68 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -26,7 +26,7 @@ function main(t) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and os.host() == "macosx" then + if is_ape and (os.host() == "macosx" or os.host() == "linux") then run_stdin = string.format('sh -c \\"%s\\"', run_stdin) end -- cgit v1.3.1 From 42fb29e925668f87329ac8ea42ec2af0f6e37634 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 03:19:20 +0300 Subject: refactor: update run_stdin command for MacOS compatibility --- tests/modules/stdin/test.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 461e76d68..665857595 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -26,9 +26,9 @@ function main(t) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and (os.host() == "macosx" or os.host() == "linux") then - run_stdin = string.format('sh -c \\"%s\\"', run_stdin) - end + if is_ape and os.host() ~= "windows" then + run_stdin = string.format("sh -c ' \\\"%s\\\" l --stdin '", xmake) + end local function test_shell(name, cmd, expect) print("testing " .. name .. ": " .. cmd) -- cgit v1.3.1 From f3b8a1296313ee90a3451257f0f2cfa2964795b0 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 03:33:23 +0300 Subject: refactor: enhance Linux APE loader mode handling and update MacOS stdin command format --- tests/modules/stdin/test.lua | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 665857595..f54bb97c7 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -4,6 +4,27 @@ function main(t) xmake = xmake:gsub("/", "\\") end + -- Fix /usr/bin/ape loader mode on Linux + if os.host() == "linux" and path.filename(xmake) == "ape" and os.isfile("/proc/self/cmdline") then + local file = io.open("/proc/self/cmdline", "rb") + if file then + local content = file:read("*a") + file:close() + if content then + local args = {} + for arg in content:gmatch("[^\0]+") do + table.insert(args, arg) + end + if #args >= 2 and path.unix(args[1]) == xmake then + xmake = path.unix(args[2]) + if not path.is_absolute(xmake) then + xmake = path.absolute(xmake) + end + end + end + end + end + -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) local function setup_xmake_alias(xmake) if path.filename(xmake):find("ape-", 1, true) then @@ -22,11 +43,11 @@ function main(t) local is_ape = path.filename(xmake):find("ape-", 1, true) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux - xmake = setup_xmake_alias(xmake) + --xmake = setup_xmake_alias(xmake) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and os.host() ~= "windows" then + if is_ape and (os.host() == "macosx" or os.host() == "linux") then run_stdin = string.format("sh -c ' \\\"%s\\\" l --stdin '", xmake) end -- cgit v1.3.1 From 39797ac3c7cce56399185ab71b37ee92cafc67d3 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 03:37:52 +0300 Subject: refactor: streamline APE loader mode handling for Linux and improve MacOS compatibility --- tests/modules/stdin/test.lua | 53 ++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index f54bb97c7..3f3539c61 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -5,49 +5,38 @@ function main(t) end -- Fix /usr/bin/ape loader mode on Linux - if os.host() == "linux" and path.filename(xmake) == "ape" and os.isfile("/proc/self/cmdline") then - local file = io.open("/proc/self/cmdline", "rb") - if file then - local content = file:read("*a") - file:close() - if content then - local args = {} - for arg in content:gmatch("[^\0]+") do - table.insert(args, arg) - end - if #args >= 2 and path.unix(args[1]) == xmake then - xmake = path.unix(args[2]) - if not path.is_absolute(xmake) then - xmake = path.absolute(xmake) + local function fix_ape_programfile(xmake) + if os.host() == "linux" and path.filename(xmake) == "ape" and os.isfile("/proc/self/cmdline") then + local file = io.open("/proc/self/cmdline", "rb") + if file then + local content = file:read("*a") + file:close() + if content then + local args = {} + for arg in content:gmatch("[^\0]+") do + table.insert(args, arg) + end + if #args >= 2 and path.unix(args[1]) == xmake then + xmake = path.unix(args[2]) + if not path.is_absolute(xmake) then + xmake = path.absolute(xmake) + end end end end end - end - - -- APE/Cosmocc workaround: force xmake name to avoid APE loader mode issues (e.g. ape-x86_64.elf) - local function setup_xmake_alias(xmake) - if path.filename(xmake):find("ape-", 1, true) then - local xmake_dir = path.join(os.tmpdir(), "xm_alias_" .. os.time()) - os.mkdir(xmake_dir) - local xmake_alias = path.join(xmake_dir, os.host() == "windows" and "xmake.exe" or "xmake") - os.cp(xmake, xmake_alias) - if os.host() ~= "windows" then - os.exec("chmod +x " .. xmake_alias) - end - return xmake_alias - end return xmake end - local is_ape = path.filename(xmake):find("ape-", 1, true) - -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux - --xmake = setup_xmake_alias(xmake) + xmake = fix_ape_programfile(xmake) + + local is_ape = path.filename(xmake):find("ape-", 1, true) + print("Using xmake programfile is_ape = ", is_ape) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and (os.host() == "macosx" or os.host() == "linux") then + if is_ape and os.host() == "macosx" then run_stdin = string.format("sh -c ' \\\"%s\\\" l --stdin '", xmake) end -- cgit v1.3.1 From 7629549db84dc57a7c5e71b93ec9baf628be5e7e Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 04:25:09 +0300 Subject: refactor: improve ape programfile detection for Linux and enhance MacOS stdin command handling --- tests/modules/stdin/test.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 3f3539c61..9911048d5 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -6,7 +6,7 @@ function main(t) -- Fix /usr/bin/ape loader mode on Linux local function fix_ape_programfile(xmake) - if os.host() == "linux" and path.filename(xmake) == "ape" and os.isfile("/proc/self/cmdline") then + if os.host() == "linux" and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then local file = io.open("/proc/self/cmdline", "rb") if file then local content = file:read("*a") @@ -36,7 +36,7 @@ function main(t) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and os.host() == "macosx" then + if is_ape and os.host() ~= "windows" then run_stdin = string.format("sh -c ' \\\"%s\\\" l --stdin '", xmake) end -- cgit v1.3.1 From c6aa73fa21bba45a591aa185b4d4a3648417b35f Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 05:02:58 +0300 Subject: refactor: enhance path resolution for xmake and improve MacOS stdin command handling --- tests/modules/stdin/test.lua | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 9911048d5..8aac5a38e 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,8 +1,18 @@ function main(t) + local function resolve_path(p) + if path.is_absolute(p) then return p end + local root = path.join(os.scriptdir(), "../../..") + local p_root = path.join(root, p) + if os.isfile(p_root) then return path.absolute(p_root) end + if os.isfile(p) then return path.absolute(p) end + return p + end + local xmake = path.unix(os.programfile()) if os.host() == "windows" then xmake = xmake:gsub("/", "\\") end + xmake = resolve_path(xmake) -- Fix /usr/bin/ape loader mode on Linux local function fix_ape_programfile(xmake) @@ -18,9 +28,7 @@ function main(t) end if #args >= 2 and path.unix(args[1]) == xmake then xmake = path.unix(args[2]) - if not path.is_absolute(xmake) then - xmake = path.absolute(xmake) - end + xmake = resolve_path(xmake) end end end @@ -31,13 +39,12 @@ function main(t) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) - local is_ape = path.filename(xmake):find("ape-", 1, true) - print("Using xmake programfile is_ape = ", is_ape) + local is_ape = path.filename(xmake):find("ape-", 1, true) ~= nil local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS if is_ape and os.host() ~= "windows" then - run_stdin = string.format("sh -c ' \\\"%s\\\" l --stdin '", xmake) + run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end local function test_shell(name, cmd, expect) -- cgit v1.3.1 From 33409f7b71773265fba3a6f688cdf97262770511 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:00:50 +0300 Subject: refactor: streamline stdin script handling for Windows compatibility --- xmake/plugins/lua/main.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 247684e24..7137ea589 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -67,12 +67,11 @@ function main() if script_content:startswith("\239\187\191") then script_content = script_content:sub(4) end - import("core.base.tty") - local shell = tty.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then + local shell = os.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() if script_content:startswith('"') and script_content:endswith('"') then - script_content = script_content:sub(2, -2) + script_content = script_content:trim('\"') end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end -- cgit v1.3.1 From eb8a34c1838e72534d3662f1da6efe273d6cc370 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:03:39 +0300 Subject: refactor: reorder resolve_path and main function definitions for improved readability --- tests/modules/stdin/test.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 8aac5a38e..784e55489 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,13 +1,13 @@ -function main(t) - local function resolve_path(p) - if path.is_absolute(p) then return p end - local root = path.join(os.scriptdir(), "../../..") - local p_root = path.join(root, p) - if os.isfile(p_root) then return path.absolute(p_root) end - if os.isfile(p) then return path.absolute(p) end - return p - end +function resolve_path(p) + if path.is_absolute(p) then return p end + local root = path.join(os.scriptdir(), "../../..") + local p_root = path.join(root, p) + if os.isfile(p_root) then return path.absolute(p_root) end + if os.isfile(p) then return path.absolute(p) end + return p +end +function main(t) local xmake = path.unix(os.programfile()) if os.host() == "windows" then xmake = xmake:gsub("/", "\\") -- cgit v1.3.1 From 20960586d09f1b83b20798223d853aa834078dbc Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:07:30 +0300 Subject: refactor: extract fix_ape_programfile function for improved readability and maintainability --- tests/modules/stdin/test.lua | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 784e55489..26c7d4b47 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -7,6 +7,28 @@ function resolve_path(p) return p end +-- Fix /usr/bin/ape loader mode on Linux +function fix_ape_programfile(xmake) + if os.host() == "linux" and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then + local file = io.open("/proc/self/cmdline", "rb") + if file then + local content = file:read("*a") + file:close() + if content then + local args = {} + for arg in content:gmatch("[^\0]+") do + table.insert(args, arg) + end + if #args >= 2 and path.unix(args[1]) == xmake then + xmake = path.unix(args[2]) + xmake = resolve_path(xmake) + end + end + end + end + return xmake +end + function main(t) local xmake = path.unix(os.programfile()) if os.host() == "windows" then @@ -14,28 +36,6 @@ function main(t) end xmake = resolve_path(xmake) - -- Fix /usr/bin/ape loader mode on Linux - local function fix_ape_programfile(xmake) - if os.host() == "linux" and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then - local file = io.open("/proc/self/cmdline", "rb") - if file then - local content = file:read("*a") - file:close() - if content then - local args = {} - for arg in content:gmatch("[^\0]+") do - table.insert(args, arg) - end - if #args >= 2 and path.unix(args[1]) == xmake then - xmake = path.unix(args[2]) - xmake = resolve_path(xmake) - end - end - end - end - return xmake - end - -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) -- cgit v1.3.1 From 16235c0f74b9957aa26fd93e0e87308296fc294f Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:08:54 +0300 Subject: refactor: replace os.host() checks with is_host() for consistency and clarity --- tests/modules/stdin/test.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 26c7d4b47..fb62fa32c 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -9,10 +9,10 @@ end -- Fix /usr/bin/ape loader mode on Linux function fix_ape_programfile(xmake) - if os.host() == "linux" and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then + if is_host("linux") and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then local file = io.open("/proc/self/cmdline", "rb") if file then - local content = file:read("*a") + local content = io.readfile("/proc/self/cmdline") file:close() if content then local args = {} @@ -31,7 +31,7 @@ end function main(t) local xmake = path.unix(os.programfile()) - if os.host() == "windows" then + if is_host("windows") then xmake = xmake:gsub("/", "\\") end xmake = resolve_path(xmake) @@ -43,7 +43,7 @@ function main(t) local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and os.host() ~= "windows" then + if is_ape and not is_host("windows") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end @@ -55,7 +55,7 @@ function main(t) local ret = -1 try({ function() - if os.host() ~= "windows" then + if not is_host("windows") then ret = os.execv("sh", { "-c", full_cmd }) else ret = os.exec(full_cmd) @@ -89,7 +89,7 @@ function main(t) end local pwsh = "" - if os.host() == "windows" then + if is_host("windows") then -- Test cmd test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") -- cgit v1.3.1 From 077e2daa5a10dbd9e20a9f25bad74bb303678c66 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:19:04 +0300 Subject: refactor: replace hardcoded utf8 BOM check with utf8.bom constant for improved maintainability --- xmake/plugins/lua/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 7137ea589..f5f7a6867 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -64,8 +64,8 @@ function main() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith("\239\187\191") then - script_content = script_content:sub(4) + if script_content:startswith(utf8.bom) then + script_content = script_content:ltrim(utf8.bom) end local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then -- cgit v1.3.1 From 84dcbd0fa5ebaa612c851fb1694993a9aa3f3968 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:19:59 +0300 Subject: refactor: streamline utf8 BOM removal process in script content handling --- xmake/plugins/lua/main.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index f5f7a6867..96ff6e40d 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -64,15 +64,11 @@ function main() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith(utf8.bom) then - script_content = script_content:ltrim(utf8.bom) - end + script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() - if script_content:startswith('"') and script_content:endswith('"') then - script_content = script_content:trim('\"') - end + script_content = script_content:trim('\"') script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end -- cgit v1.3.1 From 5e885b512315064825a96fa4865707adae9ab7ed Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:22:02 +0300 Subject: refactor: extract stdin script handling into a separate function for improved readability and maintainability --- xmake/plugins/lua/main.lua | 47 ++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 96ff6e40d..988f2af1f 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -45,6 +45,31 @@ function _list() end end +-- get script from stdin +function _get_script_from_stdin() + local script_content = io.read("*a") + if script_content then + -- remove utf8 bom + if script_content:startswith(utf8.bom) then + script_content = script_content:sub(#utf8.bom + 1) + end + local shell = os.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then + script_content = script_content:trim() + script_content = script_content:trim('\"') + script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + end + + if not script_content:find("function main", 1, true) then + script_content = "function main(...)\n" .. script_content .. "\nend" + end + + local script = os.tmpfile() .. ".lua" + io.writefile(script, script_content) + return script + end +end + function main() -- list builtin scripts @@ -61,24 +86,10 @@ function main() -- run script from stdin? local script_file_to_remove if from_stdin then - local script_content = io.read("*a") - if script_content then - -- remove utf8 bom - script_content = script_content:ltrim(utf8.bom) - local shell = os.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - script_content = script_content:trim() - script_content = script_content:trim('\"') - script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) - end - - if not script_content:find("function main", 1, true) then - script_content = "function main(...)\n" .. script_content .. "\nend" - end - - script = os.tmpfile() .. ".lua" - io.writefile(script, script_content) - script_file_to_remove = script + local script_path = _get_script_from_stdin() + if script_path then + script = script_path + script_file_to_remove = script_path end end -- cgit v1.3.1 From 8a6b95da91feb273b1ad151fb2d0dbf57b3475b0 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:24:43 +0300 Subject: Refactor BOM removal in script input handling --- xmake/plugins/lua/main.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 988f2af1f..261dffaa0 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -50,9 +50,7 @@ function _get_script_from_stdin() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith(utf8.bom) then - script_content = script_content:sub(#utf8.bom + 1) - end + script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() -- cgit v1.3.1 From e77b312440b1061261633fa41148275da74a75e5 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:27:39 +0300 Subject: refactor: simplify file handling in fix_ape_programfile function --- tests/modules/stdin/test.lua | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index fb62fa32c..6b1b4026b 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -10,19 +10,15 @@ end -- Fix /usr/bin/ape loader mode on Linux function fix_ape_programfile(xmake) if is_host("linux") and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then - local file = io.open("/proc/self/cmdline", "rb") - if file then - local content = io.readfile("/proc/self/cmdline") - file:close() - if content then - local args = {} - for arg in content:gmatch("[^\0]+") do - table.insert(args, arg) - end - if #args >= 2 and path.unix(args[1]) == xmake then - xmake = path.unix(args[2]) - xmake = resolve_path(xmake) - end + local content = io.readfile("/proc/self/cmdline") + if content then + local args = {} + for arg in content:gmatch("[^\0]+") do + table.insert(args, arg) + end + if #args >= 2 and path.unix(args[1]) == xmake then + xmake = path.unix(args[2]) + xmake = resolve_path(xmake) end end end @@ -48,7 +44,6 @@ function main(t) end local function test_shell(name, cmd, expect) - print("testing " .. name .. ": " .. cmd) local outfile = os.tmpfile() local errfile = os.tmpfile() local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) -- cgit v1.3.1 From f851d28b49caa6d19e4edc1df39b74222bda6946 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:29:02 +0300 Subject: try format --- xmake/plugins/lua/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index bb9308378..dee1707b6 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -45,11 +45,11 @@ task("lua") {'l', "list" , "k" , nil , "List all scripts." } , {'c', "command" , "k" , nil , "Run script as command" } , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } - , {nil, "stdin" , "k" , nil , "Run script from stdin", + , {nil, "stdin" , "k" , nil , "Run script from stdin", "e.g.", " - echo 'print(\"hello\")' | xmake lua --stdin", " - cat script.lua | xmake lua --stdin" - } + } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", " - xmake lua (enter interactive mode)", -- cgit v1.3.1 From d1653c5b32f4efa7fec6ab40cb93eb14b0014c38 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 10:28:45 +0300 Subject: refactor: enhance stdin script handling by improving string trimming logic --- tests/modules/stdin/test.lua | 7 ++++++- xmake/plugins/lua/main.lua | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 6b1b4026b..b0c908c3c 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -112,9 +112,14 @@ function main(t) string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2" ) + test_shell( + "pwsh_main", + string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), + "in_pwsh_main" + ) test_shell( "pwsh_multi", - string.format("%s -c \"echo \\\"print('pline1')\\nprint('pline2')\\\" | %s l --stdin\"", pwsh, xmake), + string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" ) else diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 261dffaa0..b2a104949 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -53,9 +53,14 @@ function _get_script_from_stdin() script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - script_content = script_content:trim() - script_content = script_content:trim('\"') - script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + local trimmed = script_content:trim() + if trimmed:startswith('"') and trimmed:endswith('"') then + script_content = trimmed:trim('"') + script_content = script_content:replace("\\n", "\n", {plain = true}) + :replace("\\r", "\r", {plain = true}) + else + script_content = trimmed + end end if not script_content:find("function main", 1, true) then -- cgit v1.3.1 From cd45a05d8b83235f8e2c421769f12afa063ce669 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 11:04:21 +0300 Subject: refactor: enhance fix_ape_programfile function to improve argument handling and add executable header check --- tests/modules/stdin/test.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index b0c908c3c..c6544a6b1 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -10,13 +10,13 @@ end -- Fix /usr/bin/ape loader mode on Linux function fix_ape_programfile(xmake) if is_host("linux") and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then - local content = io.readfile("/proc/self/cmdline") + local content = io.readfile("/proc/self/cmdline", {encoding = "binary"}) if content then local args = {} for arg in content:gmatch("[^\0]+") do table.insert(args, arg) end - if #args >= 2 and path.unix(args[1]) == xmake then + if #args >= 2 and (path.unix(args[1]) == xmake or path.filename(path.unix(args[1])) == path.filename(xmake)) then xmake = path.unix(args[2]) xmake = resolve_path(xmake) end @@ -35,7 +35,17 @@ function main(t) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) - local is_ape = path.filename(xmake):find("ape-", 1, true) ~= nil + local is_ape = path.filename(xmake):find("ape", 1, true) ~= nil or xmake:endswith(".com") + if not is_ape and is_host("linux") and os.isfile(xmake) then + local file = io.open(xmake, "rb") + if file then + local header = file:read(2) + file:close() + if header == "MZ" then + is_ape = true + end + end + end local run_stdin = string.format('env "%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS -- cgit v1.3.1 From 586227cf172385c9abebe6f19c2343bbf7f94a2c Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 11:32:51 +0300 Subject: refactor: improve stdin command formatting for better cross-platform compatibility --- tests/modules/stdin/test.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index c6544a6b1..e2d139e87 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -47,7 +47,10 @@ function main(t) end end - local run_stdin = string.format('env "%s" l --stdin', xmake) + local run_stdin = string.format('"%s" l --stdin', xmake) + if not is_host("windows") then + run_stdin = string.format('env "%s" l --stdin', xmake) + end -- Fix pwsh and cosmocc "exec format error" for MacOS if is_ape and not is_host("windows") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) @@ -100,7 +103,7 @@ function main(t) test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") test_shell( "cmd_multi", - string.format("cmd /c echo \"print('line1')\\nprint('line2')\" | %s l --stdin", xmake), + string.format("cmd /c \"(echo print 'line1'& echo print 'line2')\" | %s l --stdin", xmake), "line1[\r\n]+line2" ) -- Test powershell (if available) -- cgit v1.3.1 From 1f23a23c7ef92f0cc20e402abb4a510a3cb72f00 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 11:44:25 +0300 Subject: refactor: simplify script content handling in _get_script_from_stdin function --- xmake/plugins/lua/main.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index b2a104949..c7b5137ce 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -56,8 +56,6 @@ function _get_script_from_stdin() local trimmed = script_content:trim() if trimmed:startswith('"') and trimmed:endswith('"') then script_content = trimmed:trim('"') - script_content = script_content:replace("\\n", "\n", {plain = true}) - :replace("\\r", "\r", {plain = true}) else script_content = trimmed end -- cgit v1.3.1 From 30cfb753c860681adf34ddf3507119ff63f9f8be Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 12:26:20 +0300 Subject: refactor: remove unnecessary header check for ape executable on Linux --- tests/modules/stdin/test.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index e2d139e87..1780c622c 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -36,16 +36,6 @@ function main(t) xmake = fix_ape_programfile(xmake) local is_ape = path.filename(xmake):find("ape", 1, true) ~= nil or xmake:endswith(".com") - if not is_ape and is_host("linux") and os.isfile(xmake) then - local file = io.open(xmake, "rb") - if file then - local header = file:read(2) - file:close() - if header == "MZ" then - is_ape = true - end - end - end local run_stdin = string.format('"%s" l --stdin', xmake) if not is_host("windows") then -- cgit v1.3.1 From 71b0520a355f1a5e4ba0be5f2ef042118aed8432 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 13:28:27 +0300 Subject: refactor: enhance stdin command tests by adding multi-line and semicolon command handling --- tests/modules/stdin/test.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 1780c622c..f1aee7f27 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -92,10 +92,15 @@ function main(t) test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") test_shell( - "cmd_multi", + "cmd_multi_lines", string.format("cmd /c \"(echo print 'line1'& echo print 'line2')\" | %s l --stdin", xmake), "line1[\r\n]+line2" ) + test_shell( + "cmd_multi_semicolon", + string.format("cmd /c echo \"print('semi1'); print('semi2')\" | %s l --stdin", xmake), + "semi1[\r\n]+semi2" + ) -- Test powershell (if available) local pwsh = "powershell" try({ -- cgit v1.3.1 From a7d56edc0dfdcfce0d4c0eb56465c63c86bf5f98 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 13:42:32 +0300 Subject: refactor: streamline xmake path resolution and improve ape programfile handling --- tests/modules/stdin/test.lua | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index f1aee7f27..4d24d1dd6 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,3 +1,5 @@ +import("core.base.binutils") + function resolve_path(p) if path.is_absolute(p) then return p end local root = path.join(os.scriptdir(), "../../..") @@ -7,7 +9,6 @@ function resolve_path(p) return p end --- Fix /usr/bin/ape loader mode on Linux function fix_ape_programfile(xmake) if is_host("linux") and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then local content = io.readfile("/proc/self/cmdline", {encoding = "binary"}) @@ -27,15 +28,11 @@ end function main(t) local xmake = path.unix(os.programfile()) - if is_host("windows") then - xmake = xmake:gsub("/", "\\") - end - xmake = resolve_path(xmake) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) - local is_ape = path.filename(xmake):find("ape", 1, true) ~= nil or xmake:endswith(".com") + local is_ape = binutils.format(os.programfile()) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) if not is_host("windows") then -- cgit v1.3.1 From 081a3360c9d4c7d15ec035129edd25719e9fd9ab Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 13:45:17 +0300 Subject: refactor: correct variable usage for ape programfile detection in main function --- tests/modules/stdin/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 4d24d1dd6..985346d39 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -32,7 +32,7 @@ function main(t) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) - local is_ape = binutils.format(os.programfile()) == "ape" + local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) if not is_host("windows") then -- cgit v1.3.1 From 313d34ffc104c8f9371ad3d94ad633112d2430bc Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 13:58:47 +0300 Subject: refactor: correct path handling for xmake program file in main function --- tests/modules/stdin/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 985346d39..7f01b6f86 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -27,7 +27,7 @@ function fix_ape_programfile(xmake) end function main(t) - local xmake = path.unix(os.programfile()) + local xmake = path.translate(os.programfile()) -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux xmake = fix_ape_programfile(xmake) -- cgit v1.3.1 From 93d38be02f934c234dd6e62f5fd6cfd25d4d59c4 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 14:07:20 +0300 Subject: refactor: enhance test_shell function for improved command execution and output handling --- tests/modules/stdin/test.lua | 93 +++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 7f01b6f86..af2954517 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -26,6 +26,37 @@ function fix_ape_programfile(xmake) return xmake end +function test_shell(t, name, cmd, expect) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) + local ret = -1 + try({ + function() + if not is_host("windows") then + ret = os.execv("sh", { "-c", full_cmd }) + else + ret = os.exec(full_cmd) + end + end, + }) + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + local passed = out:find(expect) + t:require(passed) + os.tryrm(outfile) + os.tryrm(errfile) +end + function main(t) local xmake = path.translate(os.programfile()) @@ -43,57 +74,19 @@ function main(t) run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end - local function test_shell(name, cmd, expect) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) - local ret = -1 - try({ - function() - if not is_host("windows") then - ret = os.execv("sh", { "-c", full_cmd }) - else - ret = os.exec(full_cmd) - end - end, - }) - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - if out and out:find("\0", 1, true) then - out = out:gsub("\0", "") - end - end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) - end - local passed = out:find(expect) - if passed then - print(" -> passed") - else - print(" -> failed") - end - print(" out: " .. (out or "")) - print(" err: " .. (err or "")) - if not passed then - raise("[test_stdin]: Test failed! Expect: ", expect) - end - os.tryrm(outfile) - os.tryrm(errfile) - end - local pwsh = "" if is_host("windows") then -- Test cmd - test_shell("cmd_single", string.format("cmd /c echo \"print('hello_cmd')\" | %s l --stdin", xmake), "hello_cmd") - test_shell("cmd_calc", string.format('cmd /c echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell(t, "cmd_single", string.format("cmd /c echo print 'hello_cmd' | %s l --stdin", xmake), "hello_cmd") + test_shell(t, "cmd_calc", string.format('cmd /c echo local f = 1+1; print^(f^) | %s l --stdin', xmake), "2") test_shell( + t, "cmd_multi_lines", - string.format("cmd /c \"(echo print 'line1'& echo print 'line2')\" | %s l --stdin", xmake), + string.format("cmd /c \"(echo print 'line1'&& echo print 'line2')\" | %s l --stdin", xmake), "line1[\r\n]+line2" ) test_shell( + t, "cmd_multi_semicolon", string.format("cmd /c echo \"print('semi1'); print('semi2')\" | %s l --stdin", xmake), "semi1[\r\n]+semi2" @@ -108,21 +101,25 @@ function main(t) end, }) test_shell( + t, "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh" ) test_shell( + t, "pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2" ) test_shell( + t, "pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), "in_pwsh_main" ) test_shell( + t, "pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" @@ -147,35 +144,41 @@ function main(t) if pwsh ~= "" then test_shell( + t, "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), "hello_pwsh" ) test_shell( + t, "pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), "2" ) test_shell( + t, "pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), "in_pwsh_main" ) test_shell( + t, "pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" ) end - test_shell("sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") - test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell(t, "sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") + test_shell(t, "sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") test_shell( + t, "sh_main", string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), "in_sh_main" ) test_shell( + t, "sh_multi", string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), "shell_line1[\r\n]+shell_line2" -- cgit v1.3.1 From 7294865c853930c4a50009cf3be1f8d1b302198d Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 14:36:27 +0300 Subject: refactor: simplify ape program file handling in test cases and remove unused functions --- core/src/xmake/engine.c | 24 ++++++++++++++++++++++++ tests/modules/stdin/test.lua | 39 +++------------------------------------ 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index df5ae06be..7a76da7a1 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -874,6 +874,30 @@ static tb_bool_t xm_engine_get_program_file(xm_engine_t *engine, tb_char_t **arg ssize_t size = readlink(XM_PROC_SELF_FILE, path, (size_t)maxn); if (size > 0 && size < maxn) { path[size] = '\0'; +#if defined(TB_CONFIG_OS_LINUX) + // fix /usr/bin/ape for cosmocc + if (size > 3 && !tb_strcmp(path + size - 3, "ape")) { + FILE* fp = fopen("/proc/self/cmdline", "rb"); + if (fp) { + tb_char_t line[TB_PATH_MAXN * 2]; + if (fread(line, 1, sizeof(line), fp) > 0) { + tb_char_t* p = line; + // if argv[0] is /usr/bin/ape, we use argv[1] + if (tb_strstr(p, "ape")) { + p += tb_strlen(p) + 1; + } + // get absolute path + if (p < line + sizeof(line) && *p) { + tb_char_t buf[TB_PATH_MAXN]; + if (tb_path_absolute(p, buf, sizeof(buf))) { + tb_strlcpy(path, buf, maxn); + } + } + } + fclose(fp); + } + } +#endif ok = tb_true; } #elif defined(TB_CONFIG_OS_BSD) && defined(KERN_PROC_PATHNAME) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index af2954517..d92b0f1f8 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,31 +1,5 @@ import("core.base.binutils") -function resolve_path(p) - if path.is_absolute(p) then return p end - local root = path.join(os.scriptdir(), "../../..") - local p_root = path.join(root, p) - if os.isfile(p_root) then return path.absolute(p_root) end - if os.isfile(p) then return path.absolute(p) end - return p -end - -function fix_ape_programfile(xmake) - if is_host("linux") and path.filename(xmake):find("ape", 1, true) and os.isfile("/proc/self/cmdline") then - local content = io.readfile("/proc/self/cmdline", {encoding = "binary"}) - if content then - local args = {} - for arg in content:gmatch("[^\0]+") do - table.insert(args, arg) - end - if #args >= 2 and (path.unix(args[1]) == xmake or path.filename(path.unix(args[1])) == path.filename(xmake)) then - xmake = path.unix(args[2]) - xmake = resolve_path(xmake) - end - end - end - return xmake -end - function test_shell(t, name, cmd, expect) local outfile = os.tmpfile() local errfile = os.tmpfile() @@ -60,17 +34,10 @@ end function main(t) local xmake = path.translate(os.programfile()) - -- Fix pwsh and cosmocc "err: ape error: l: not found (maybe chmod +x or ./ needed)" for Linux - xmake = fix_ape_programfile(xmake) - local is_ape = binutils.format(xmake) == "ape" - local run_stdin = string.format('"%s" l --stdin', xmake) - if not is_host("windows") then - run_stdin = string.format('env "%s" l --stdin', xmake) - end - -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and not is_host("windows") then + -- Fix pwsh and cosmocc "exec format error" for MacOS + if is_ape and not is_host("windows") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end @@ -78,7 +45,7 @@ function main(t) if is_host("windows") then -- Test cmd test_shell(t, "cmd_single", string.format("cmd /c echo print 'hello_cmd' | %s l --stdin", xmake), "hello_cmd") - test_shell(t, "cmd_calc", string.format('cmd /c echo local f = 1+1; print^(f^) | %s l --stdin', xmake), "2") + test_shell(t, "cmd_calc", string.format("cmd /c echo local f = 1+1; print^(f^) | %s l --stdin", xmake), "2") test_shell( t, "cmd_multi_lines", -- cgit v1.3.1 From fb950ed66855524a213ed9144c74bfa0f4f91f17 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 15:29:11 +0300 Subject: refactor: update MacOS handling in main function for xmake execution --- tests/modules/stdin/test.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index d92b0f1f8..078d374ea 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -33,11 +33,10 @@ end function main(t) local xmake = path.translate(os.programfile()) - local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and not is_host("windows") then + if is_ape and is_host("macosx") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end -- cgit v1.3.1 From 9f82e7f5c72f8f120c24c05cb25468226dbc0ae9 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 15:49:07 +0300 Subject: rerun for cosmocc ci --- tests/modules/stdin/test.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 078d374ea..f3490a064 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -39,7 +39,6 @@ function main(t) if is_ape and is_host("macosx") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end - local pwsh = "" if is_host("windows") then -- Test cmd -- cgit v1.3.1 From 307947cc644243e9b8248a14d8ee2b3b94a549fc Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 15:58:01 +0300 Subject: refactor: remove MacOS specific workaround for pwsh and cosmocc exec format error --- tests/modules/stdin/test.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index f3490a064..2c3460f0d 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -35,10 +35,6 @@ function main(t) local xmake = path.translate(os.programfile()) local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) - -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and is_host("macosx") then - run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) - end local pwsh = "" if is_host("windows") then -- Test cmd -- cgit v1.3.1 From 03f89e0d3a6bff306ad95705afe18c5e12792bbc Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 16:17:42 +0300 Subject: refactor: fix pwsh and cosmocc "exec format error" handling for MacOS --- tests/modules/stdin/test.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 2c3460f0d..f3490a064 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -35,6 +35,10 @@ function main(t) local xmake = path.translate(os.programfile()) local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) + -- Fix pwsh and cosmocc "exec format error" for MacOS + if is_ape and is_host("macosx") then + run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) + end local pwsh = "" if is_host("windows") then -- Test cmd -- cgit v1.3.1 From d46368bd6d2d5c0331e701a1cfa62590407f074c Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 16:46:22 +0300 Subject: try --- tests/modules/stdin/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index f3490a064..ae550e789 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -36,7 +36,7 @@ function main(t) local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and is_host("macosx") then + if is_ape and not is_host("windows") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end local pwsh = "" -- cgit v1.3.1 From 3bf7d52392bd9489ce7e580120dec8dac7d7c29f Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 22:10:30 +0800 Subject: Update engine.c --- core/src/xmake/engine.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 7a76da7a1..32a4855cf 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -874,32 +874,11 @@ static tb_bool_t xm_engine_get_program_file(xm_engine_t *engine, tb_char_t **arg ssize_t size = readlink(XM_PROC_SELF_FILE, path, (size_t)maxn); if (size > 0 && size < maxn) { path[size] = '\0'; -#if defined(TB_CONFIG_OS_LINUX) - // fix /usr/bin/ape for cosmocc - if (size > 3 && !tb_strcmp(path + size - 3, "ape")) { - FILE* fp = fopen("/proc/self/cmdline", "rb"); - if (fp) { - tb_char_t line[TB_PATH_MAXN * 2]; - if (fread(line, 1, sizeof(line), fp) > 0) { - tb_char_t* p = line; - // if argv[0] is /usr/bin/ape, we use argv[1] - if (tb_strstr(p, "ape")) { - p += tb_strlen(p) + 1; - } - // get absolute path - if (p < line + sizeof(line) && *p) { - tb_char_t buf[TB_PATH_MAXN]; - if (tb_path_absolute(p, buf, sizeof(buf))) { - tb_strlcpy(path, buf, maxn); - } - } - } - fclose(fp); + // ignore cosmocc ape binary, we fallback to argv[0], .e.g /usr/bin/ape, /home/ruki/.ape-1.10 + if (!tb_strstr(path, "ape")) { + ok = tb_true; } } -#endif - ok = tb_true; - } #elif defined(TB_CONFIG_OS_BSD) && defined(KERN_PROC_PATHNAME) // only for FreeBSD and OpenBSD, https://github.com/xmake-io/xmake/issues/2948 tb_int_t mib[4]; -- cgit v1.3.1 From 7799a7947779a1c962e8c3256bcd615891f2a338 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 22:34:42 +0800 Subject: Update test.lua --- tests/modules/stdin/test.lua | 134 ++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 73 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index ae550e789..db37a0806 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,6 +1,7 @@ import("core.base.binutils") +import("lib.detect.find_tool") -function test_shell(t, name, cmd, expect) +function _test_shell(t, name, cmd, expect) local outfile = os.tmpfile() local errfile = os.tmpfile() local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) @@ -31,7 +32,7 @@ function test_shell(t, name, cmd, expect) os.tryrm(errfile) end -function main(t) +function _get_xmake_and_run_stdin() local xmake = path.translate(os.programfile()) local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) @@ -39,114 +40,101 @@ function main(t) if is_ape and not is_host("windows") then run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) end - local pwsh = "" + return xmake, run_stdin +end + +function test_sh(t) + local xmake, run_stdin = _get_xmake_and_run_stdin() if is_host("windows") then -- Test cmd - test_shell(t, "cmd_single", string.format("cmd /c echo print 'hello_cmd' | %s l --stdin", xmake), "hello_cmd") - test_shell(t, "cmd_calc", string.format("cmd /c echo local f = 1+1; print^(f^) | %s l --stdin", xmake), "2") - test_shell( + _test_shell(t, "cmd_single", string.format("cmd /c echo print 'hello_cmd' | %s l --stdin", xmake), "hello_cmd") + _test_shell(t, "cmd_calc", string.format("cmd /c echo local f = 1+1; print^(f^) | %s l --stdin", xmake), "2") + _test_shell( t, "cmd_multi_lines", string.format("cmd /c \"(echo print 'line1'&& echo print 'line2')\" | %s l --stdin", xmake), "line1[\r\n]+line2" ) - test_shell( + _test_shell( t, "cmd_multi_semicolon", string.format("cmd /c echo \"print('semi1'); print('semi2')\" | %s l --stdin", xmake), "semi1[\r\n]+semi2" ) - -- Test powershell (if available) - local pwsh = "powershell" - try({ - function() - if os.exec("pwsh -v") == 0 then - pwsh = "pwsh" - end - end, - }) - test_shell( - t, - "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), - "hello_pwsh" - ) - test_shell( - t, - "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), - "2" - ) - test_shell( + else + -- Linux/MacOS + _test_shell(t, "sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") + _test_shell(t, "sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + _test_shell( t, - "pwsh_main", - string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), - "in_pwsh_main" + "sh_main", + string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), + "in_sh_main" ) - test_shell( + _test_shell( t, - "pwsh_multi", - string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), - "pline1[\r\n]+pline2" + "sh_multi", + string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), + "shell_line1[\r\n]+shell_line2" ) - else - -- Linux/MacOS - local pwsh = "" - try({ - function() - os.iorun("pwsh -v") - pwsh = "pwsh" - end, - }) - if pwsh == "" then - try({ - function() - os.iorun("powershell -v") - pwsh = "powershell" - end, - }) - end + end +end - if pwsh ~= "" then - test_shell( +function test_powershell(t) + local xmake, run_stdin = _get_xmake_and_run_stdin() + local pwsh = find_tool("powershell") + if pwsh then + pwsh = pwsh.program + if is_host("windows") then + _test_shell( + t, + "pwsh_single", + string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), + "hello_pwsh" + ) + _test_shell( + t, + "pwsh_calc", + string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), + "2" + ) + _test_shell( + t, + "pwsh_main", + string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), + "in_pwsh_main" + ) + _test_shell( + t, + "pwsh_multi", + string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), + "pline1[\r\n]+pline2" + ) + else + _test_shell( t, "pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), "hello_pwsh" ) - test_shell( + _test_shell( t, "pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), "2" ) - test_shell( + _test_shell( t, "pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), "in_pwsh_main" ) - test_shell( + _test_shell( t, "pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" ) end - - test_shell(t, "sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") - test_shell(t, "sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - test_shell( - t, - "sh_main", - string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), - "in_sh_main" - ) - test_shell( - t, - "sh_multi", - string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), - "shell_line1[\r\n]+shell_line2" - ) end end -- cgit v1.3.1 From 0c76b46b5bd1250edd45493f6839c60d592724ca Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 22:43:31 +0800 Subject: Update test.lua --- tests/modules/stdin/test.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index db37a0806..dd781e28b 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -34,12 +34,7 @@ end function _get_xmake_and_run_stdin() local xmake = path.translate(os.programfile()) - local is_ape = binutils.format(xmake) == "ape" local run_stdin = string.format('"%s" l --stdin', xmake) - -- Fix pwsh and cosmocc "exec format error" for MacOS - if is_ape and not is_host("windows") then - run_stdin = string.format("sh -c ' \"%s\" l --stdin '", xmake) - end return xmake, run_stdin end -- cgit v1.3.1 From 2e1c785938ae107734f4e4f1c36e57feae71aca6 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 23:47:42 +0800 Subject: Update test.lua --- tests/modules/stdin/test.lua | 156 ++++++++++--------------------------------- 1 file changed, 36 insertions(+), 120 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index dd781e28b..6c9d49587 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,135 +1,51 @@ import("core.base.binutils") import("lib.detect.find_tool") -function _test_shell(t, name, cmd, expect) - local outfile = os.tmpfile() - local errfile = os.tmpfile() - local full_cmd = string.format('%s > "%s" 2> "%s"', cmd, outfile, errfile) - local ret = -1 - try({ - function() - if not is_host("windows") then - ret = os.execv("sh", { "-c", full_cmd }) - else - ret = os.exec(full_cmd) - end - end, - }) - local out = "" - if os.isfile(outfile) then - out = io.readfile(outfile) - if out and out:find("\0", 1, true) then - out = out:gsub("\0", "") - end +function _run_sh(t, name, cmd, expect) + if not is_host("windows") then + local xmake = path.translate(os.programfile()) + local run_stdin = string.format('"%s" l --stdin', xmake) + local outdata = os.iorunv("sh", {"-c", cmd .. " | " .. run_stdin}) or "" + t:are_equal(outdata:trim(), expect) end - local err = "" - if os.isfile(errfile) then - err = io.readfile(errfile) +end + +function _run_cmd(t, name, cmd, expect) + if is_host("windows") then + local xmake = path.translate(os.programfile()) + local run_stdin = string.format('"%s" l --stdin', xmake) + local outdata = os.iorunv("cmd", {"/c", cmd .. " | " .. run_stdin}) or "" + t:are_equal(outdata:trim(), expect) end - local passed = out:find(expect) - t:require(passed) - os.tryrm(outfile) - os.tryrm(errfile) end -function _get_xmake_and_run_stdin() +function _run_pwsh(t, name, cmd, expect) local xmake = path.translate(os.programfile()) local run_stdin = string.format('"%s" l --stdin', xmake) - return xmake, run_stdin + local pwsh = find_tool("powershell") + if pwsh then + local outdata = os.iorunv(pwsh.program, {"-c", cmd .. " | " .. run_stdin}) or "" + t:are_equal(outdata:trim(), expect) + end end function test_sh(t) - local xmake, run_stdin = _get_xmake_and_run_stdin() - if is_host("windows") then - -- Test cmd - _test_shell(t, "cmd_single", string.format("cmd /c echo print 'hello_cmd' | %s l --stdin", xmake), "hello_cmd") - _test_shell(t, "cmd_calc", string.format("cmd /c echo local f = 1+1; print^(f^) | %s l --stdin", xmake), "2") - _test_shell( - t, - "cmd_multi_lines", - string.format("cmd /c \"(echo print 'line1'&& echo print 'line2')\" | %s l --stdin", xmake), - "line1[\r\n]+line2" - ) - _test_shell( - t, - "cmd_multi_semicolon", - string.format("cmd /c echo \"print('semi1'); print('semi2')\" | %s l --stdin", xmake), - "semi1[\r\n]+semi2" - ) - else - -- Linux/MacOS - _test_shell(t, "sh_single", string.format("echo \"print('hello_sh')\" | %s l --stdin", xmake), "hello_sh") - _test_shell(t, "sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") - _test_shell( - t, - "sh_main", - string.format("echo \"function main() print('in_sh_main') end\" | %s l --stdin", xmake), - "in_sh_main" - ) - _test_shell( - t, - "sh_multi", - string.format("printf \"print('shell_line1')\\nprint('shell_line2')\" | %s l --stdin", xmake), - "shell_line1[\r\n]+shell_line2" - ) - end + _run_sh(t, "sh_single", "echo \"print('hello_sh')\"", "hello_sh") + _run_sh(t, "sh_calc", 'echo "local f = 1+1; print(f)"', "2") + _run_sh(t, "sh_main", "echo \"function main() print('in_sh_main') end\"", "in_sh_main") + _run_sh(t, "sh_multi", "printf \"print('shell_line1')\\nprint('shell_line2')\"", "shell_line1\nshell_line2") end -function test_powershell(t) - local xmake, run_stdin = _get_xmake_and_run_stdin() - local pwsh = find_tool("powershell") - if pwsh then - pwsh = pwsh.program - if is_host("windows") then - _test_shell( - t, - "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), - "hello_pwsh" - ) - _test_shell( - t, - "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), - "2" - ) - _test_shell( - t, - "pwsh_main", - string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), - "in_pwsh_main" - ) - _test_shell( - t, - "pwsh_multi", - string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), - "pline1[\r\n]+pline2" - ) - else - _test_shell( - t, - "pwsh_single", - string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s"', pwsh, run_stdin), - "hello_pwsh" - ) - _test_shell( - t, - "pwsh_calc", - string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s"', pwsh, run_stdin), - "2" - ) - _test_shell( - t, - "pwsh_main", - string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), - "in_pwsh_main" - ) - _test_shell( - t, - "pwsh_multi", - string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), - "pline1[\r\n]+pline2" - ) - end - end +function test_cmd(t) + _run_cmd(t, "cmd_single", "echo print 'hello_cmd'", "hello_cmd") + _run_cmd(t, "cmd_calc", "echo local f = 1+1; print^(f^)", "2") + _run_cmd(t, "cmd_multi_lines", "(echo print 'line1'&& echo print 'line2')", "line1\r\nline2") + _run_cmd(t, "cmd_multi_semicolon", "echo \"print('semi1'); print('semi2')\"", "semi1\r\nsemi2") +end + +function test_pwsh(t) + _run_pwsh(t, "pwsh_single", "echo \"print('hello_pwsh')\"", "hello_pwsh") + _run_pwsh(t, "pwsh_calc", "echo \"local f = 1+1; print(f)\"", "2") + _run_pwsh(t, "pwsh_main", "echo \"function main() print('in_pwsh_main') end\"", "in_pwsh_main") + _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\r\npline2") end -- cgit v1.3.1 From 1e9e8d25b8180d05ac8c99073f31cd6b085dc4a9 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 23:49:48 +0800 Subject: Update test.lua --- tests/modules/stdin/test.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 6c9d49587..351955f71 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -1,4 +1,3 @@ -import("core.base.binutils") import("lib.detect.find_tool") function _run_sh(t, name, cmd, expect) @@ -20,12 +19,14 @@ function _run_cmd(t, name, cmd, expect) end function _run_pwsh(t, name, cmd, expect) - local xmake = path.translate(os.programfile()) - local run_stdin = string.format('"%s" l --stdin', xmake) - local pwsh = find_tool("powershell") - if pwsh then - local outdata = os.iorunv(pwsh.program, {"-c", cmd .. " | " .. run_stdin}) or "" - t:are_equal(outdata:trim(), expect) + if is_host("windows") then + local xmake = path.translate(os.programfile()) + local run_stdin = string.format('"%s" l --stdin', xmake) + local pwsh = find_tool("powershell") + if pwsh then + local outdata = os.iorunv(pwsh.program, {"-c", cmd .. " | " .. run_stdin}) or "" + t:are_equal(outdata:trim(), expect) + end end end @@ -47,5 +48,5 @@ function test_pwsh(t) _run_pwsh(t, "pwsh_single", "echo \"print('hello_pwsh')\"", "hello_pwsh") _run_pwsh(t, "pwsh_calc", "echo \"local f = 1+1; print(f)\"", "2") _run_pwsh(t, "pwsh_main", "echo \"function main() print('in_pwsh_main') end\"", "in_pwsh_main") - _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\r\npline2") + _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')`nprint('pline2')\"", "pline1\r\npline2") end -- cgit v1.3.1 From 2ddc34d3ecfe4b3cdbf8370fdbcc4c46f61f54d0 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 2 Feb 2026 23:51:44 +0800 Subject: Fix shell and command test cases for output consistency --- tests/modules/stdin/test.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 351955f71..d739e9bab 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -32,14 +32,14 @@ end function test_sh(t) _run_sh(t, "sh_single", "echo \"print('hello_sh')\"", "hello_sh") - _run_sh(t, "sh_calc", 'echo "local f = 1+1; print(f)"', "2") + _run_sh(t, "sh_calc", "echo \"local f = 1+1; print(f)\"", "2") _run_sh(t, "sh_main", "echo \"function main() print('in_sh_main') end\"", "in_sh_main") _run_sh(t, "sh_multi", "printf \"print('shell_line1')\\nprint('shell_line2')\"", "shell_line1\nshell_line2") end function test_cmd(t) _run_cmd(t, "cmd_single", "echo print 'hello_cmd'", "hello_cmd") - _run_cmd(t, "cmd_calc", "echo local f = 1+1; print^(f^)", "2") + _run_cmd(t, "cmd_calc", "echo local f = 1+1; print(f)", "2") _run_cmd(t, "cmd_multi_lines", "(echo print 'line1'&& echo print 'line2')", "line1\r\nline2") _run_cmd(t, "cmd_multi_semicolon", "echo \"print('semi1'); print('semi2')\"", "semi1\r\nsemi2") end @@ -48,5 +48,5 @@ function test_pwsh(t) _run_pwsh(t, "pwsh_single", "echo \"print('hello_pwsh')\"", "hello_pwsh") _run_pwsh(t, "pwsh_calc", "echo \"local f = 1+1; print(f)\"", "2") _run_pwsh(t, "pwsh_main", "echo \"function main() print('in_pwsh_main') end\"", "in_pwsh_main") - _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')`nprint('pline2')\"", "pline1\r\npline2") + _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\r\npline2") end -- cgit v1.3.1 From 7d1615632117405b5078aef5a3ecdb6dd5d0edf0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 3 Feb 2026 10:03:26 +0800 Subject: Update test.lua --- tests/modules/stdin/test.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index d739e9bab..60e8ca1e5 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -12,7 +12,7 @@ end function _run_cmd(t, name, cmd, expect) if is_host("windows") then local xmake = path.translate(os.programfile()) - local run_stdin = string.format('"%s" l --stdin', xmake) + local run_stdin = string.format('%s l --stdin', xmake) local outdata = os.iorunv("cmd", {"/c", cmd .. " | " .. run_stdin}) or "" t:are_equal(outdata:trim(), expect) end @@ -21,7 +21,7 @@ end function _run_pwsh(t, name, cmd, expect) if is_host("windows") then local xmake = path.translate(os.programfile()) - local run_stdin = string.format('"%s" l --stdin', xmake) + local run_stdin = string.format('%s l --stdin', xmake) local pwsh = find_tool("powershell") if pwsh then local outdata = os.iorunv(pwsh.program, {"-c", cmd .. " | " .. run_stdin}) or "" @@ -40,13 +40,13 @@ end function test_cmd(t) _run_cmd(t, "cmd_single", "echo print 'hello_cmd'", "hello_cmd") _run_cmd(t, "cmd_calc", "echo local f = 1+1; print(f)", "2") - _run_cmd(t, "cmd_multi_lines", "(echo print 'line1'&& echo print 'line2')", "line1\r\nline2") - _run_cmd(t, "cmd_multi_semicolon", "echo \"print('semi1'); print('semi2')\"", "semi1\r\nsemi2") + _run_cmd(t, "cmd_multi_lines", "(echo print 'line1' && echo print 'line2')", "line1\nline2") + _run_cmd(t, "cmd_multi_semicolon", "echo print('semi1'); print('semi2')", "semi1\nsemi2") end function test_pwsh(t) _run_pwsh(t, "pwsh_single", "echo \"print('hello_pwsh')\"", "hello_pwsh") _run_pwsh(t, "pwsh_calc", "echo \"local f = 1+1; print(f)\"", "2") _run_pwsh(t, "pwsh_main", "echo \"function main() print('in_pwsh_main') end\"", "in_pwsh_main") - _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\r\npline2") + _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\npline2") end -- cgit v1.3.1 From b72e271e4ca2b59170819295eaa972ce149096b2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 3 Feb 2026 10:17:09 +0800 Subject: Fix syntax for pwsh_multi test case --- tests/modules/stdin/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 60e8ca1e5..323ba6f81 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -48,5 +48,5 @@ function test_pwsh(t) _run_pwsh(t, "pwsh_single", "echo \"print('hello_pwsh')\"", "hello_pwsh") _run_pwsh(t, "pwsh_calc", "echo \"local f = 1+1; print(f)\"", "2") _run_pwsh(t, "pwsh_main", "echo \"function main() print('in_pwsh_main') end\"", "in_pwsh_main") - _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\"; echo \"print('pline2')\"", "pline1\npline2") + _run_pwsh(t, "pwsh_multi", "echo \"print('pline1')\" \"print('pline2')\"", "pline1\npline2") end -- cgit v1.3.1 From f99b99b2ae3cfeb47356e6542c393bba009f8583 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 3 Feb 2026 10:17:50 +0800 Subject: Refactor script content handling in main.lua Removed Windows-specific shell handling for script content. --- xmake/plugins/lua/main.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index c7b5137ce..772faa2c6 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -51,16 +51,6 @@ function _get_script_from_stdin() if script_content then -- remove utf8 bom script_content = script_content:ltrim(utf8.bom) - local shell = os.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - local trimmed = script_content:trim() - if trimmed:startswith('"') and trimmed:endswith('"') then - script_content = trimmed:trim('"') - else - script_content = trimmed - end - end - if not script_content:find("function main", 1, true) then script_content = "function main(...)\n" .. script_content .. "\nend" end -- cgit v1.3.1 From 7a9f668793b387efc3d657ceedbd0ab913dab4e0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 3 Feb 2026 10:22:14 +0800 Subject: Update engine.c --- core/src/xmake/engine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 32a4855cf..9c02d8487 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -875,7 +875,8 @@ static tb_bool_t xm_engine_get_program_file(xm_engine_t *engine, tb_char_t **arg if (size > 0 && size < maxn) { path[size] = '\0'; // ignore cosmocc ape binary, we fallback to argv[0], .e.g /usr/bin/ape, /home/ruki/.ape-1.10 - if (!tb_strstr(path, "ape")) { + tb_char_t const* filename = tb_strrchr(path, '/'); + if (!tb_strstr(filename ? filename + 1 : path, "ape")) { ok = tb_true; } } -- cgit v1.3.1