From 5cd2c21c808ff3ce1c89eb230b97be5940ed29de Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Sep 2025 00:58:16 +0800 Subject: improve to run script --- xmake/modules/utils/run_script.lua | 154 +++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 xmake/modules/utils/run_script.lua (limited to 'xmake/modules/utils/run_script.lua') diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua new file mode 100644 index 000000000..d2e04f8ac --- /dev/null +++ b/xmake/modules/utils/run_script.lua @@ -0,0 +1,154 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author ruki +-- @file run.lua +-- + +-- imports +import("core.sandbox.module") + +-- print verbose log +function _print_vlog(script_type, script_name, args, opt) + if not opt.verbose then + return + end + cprintf("running %s ${underline}%s${reset}", script_type, script_name) + if args.n > 0 then + print(" with args:") + if not opt.diagnosis then + for i = 1, args.n do + print(" - " .. todisplay(args[i])) + end + else + utils.dump(table.unpack(args, 1, args.n)) + end + else + print(".") + end +end + +function _is_callable(func) + if type(func) == "function" then + return true + elseif type(func) == "table" then + local meta = debug.getmetatable(func) + if meta and meta.__call then + return true + end + end +end + +function _run_script(script, args, opt) + + local func + local printresult = false + local script_type, script_name + + -- import and run script + 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) + func = import(path.basename(script), {rootdir = path.directory(script), anonymous = true}) + elseif os.isfile(path.join(os.scriptdir(), "scripts", script .. ".lua")) then + + -- run builtin lua script (xmake lua echo "hello xmake") + script_type, script_name = "builtin lua script", script + func = import("scripts." .. script, {anonymous = true}) + else + + -- attempt to find the builtin module + local object = nil + for _, name in ipairs(script:split("%.")) do + object = object and object[name] or module.get(name) + if not object then + break + end + end + if object then + -- run builtin modules (xmake lua core.xxx.xxx) + script_type, script_name = "builtin module", script + func = object + else + -- run imported modules (xmake lua core.xxx.xxx) + script_type, script_name = "imported module", script + func = import(script, {anonymous = true}) + end + printresult = true + end + + -- print verbose log + _print_vlog(script_type or "script", script_name or "", args, opt) + + -- dump func() result + if _is_callable(func) then + local result = table.pack(func(table.unpack(args, 1, args.n))) + if printresult and result and result.n ~= 0 then + utils.dump(table.unpack(result, 1, result.n)) + end + else + -- dump variables directly + utils.dump(func) + end +end + +function _run_commanad(command, args, opt) + local tmpfile = os.tmpfile() .. ".lua" + io.writefile(tmpfile, "function main(...)\n" .. command .. "\nend") + return _run_script(tmpfile, args, opt) +end + +function _get_args(opt) + opt = opt or {} + + -- get arguments + local args = opt.arguments or {} + args.n = #args + + -- get deserialize tag + local deserialize = opt.deserialize + if not deserialize then + return args + end + deserialize = tostring(deserialize) + + -- deserialize prefixed arguments + for i, value in ipairs(args) do + if value:startswith(deserialize) then + local v, err = string.deserialize(value:sub(#deserialize + 1)) + if err then + raise(err) + else + args[i] = v + end + end + end + return args +end + +function main(script, opt) + opt = opt or {} + local result + local curdir = opt.curdir or os.workingdir() + local oldir = os.cd(curdir) + if opt.command then + result = _run_commanad(script, _get_args(opt), opt) + end + result = _run_script(script, _get_args(opt), opt) + os.cd(oldir) + return result +end -- cgit v1.3.1 From 15c0177361f6a6b488ab6937d088f4a0a711a086 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Sep 2025 22:53:15 +0800 Subject: run script in thread --- xmake/modules/utils/run_script.lua | 45 +++++++++++++++++++++++++++++++++----- xmake/plugins/lua/main.lua | 8 +++---- 2 files changed, 43 insertions(+), 10 deletions(-) (limited to 'xmake/modules/utils/run_script.lua') diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index d2e04f8ac..709580f1b 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -20,6 +20,7 @@ -- imports import("core.sandbox.module") +import("core.base.thread") -- print verbose log function _print_vlog(script_type, script_name, args, opt) @@ -109,7 +110,7 @@ end function _run_commanad(command, args, opt) local tmpfile = os.tmpfile() .. ".lua" io.writefile(tmpfile, "function main(...)\n" .. command .. "\nend") - return _run_script(tmpfile, args, opt) + _run_script(tmpfile, args, opt) end function _get_args(opt) @@ -140,15 +141,47 @@ function _get_args(opt) return args end +function _run(script, opt) + if opt.command then + _run_commanad(script, _get_args(opt), opt) + else + _run_script(script, _get_args(opt), opt) + end +end + +function _run_in_thread(script, opt) + import("utils.run_script", {anonymous = true})(script, opt) +end + +-- run lua script +-- +-- @param script the script file or string or module name +-- e.g. /tmp/test.lua, "print("hello")", "utils.bin2c" +-- @param opt the options +-- - curdir the currect directory +-- - command run script as command +-- - deserialize deserialize arguments starts with given prefix +-- - arguments the script arguments +-- - thread run script in a new native thread +-- - verbose enable verbose output +-- - diagnosis enable diagnosis output function main(script, opt) opt = opt or {} - local result local curdir = opt.curdir or os.workingdir() local oldir = os.cd(curdir) - if opt.command then - result = _run_commanad(script, _get_args(opt), opt) + if opt.thread then + local thread_opt = { + curdir = curdir, + command = opt.command, + deserialize = opt.deserialize, + arguments = opt.arguments, + verbose = opt.verbose, + diagnosis = opt.diagnosis + } + local t = thread.start_named("utils.run_script", _run_in_thread, script, thread_opt) + t:wait(-1) + else + _run(script, opt) end - result = _run_script(script, _get_args(opt), opt) os.cd(oldir) - return result end diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 6e0ca88be..2b0a9efe2 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -55,15 +55,15 @@ function main() -- run script local script = option.get("script") if script then - return run_script(script, { + 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")}) + else + -- enter interactive mode + sandbox.interactive() end - - -- enter interactive mode - sandbox.interactive() end -- cgit v1.3.1 From 4d11d90ba502bcd82a72c2ea66b1115897d81c52 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Sep 2025 22:57:52 +0800 Subject: improve bin2c --- xmake/modules/private/utils/batchcmds.lua | 23 +++++++++++++++++++++++ xmake/modules/utils/run_script.lua | 10 +++++++++- xmake/rules/utils/bin2c/xmake.lua | 4 ++-- 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'xmake/modules/utils/run_script.lua') diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua index 944507397..544c94c2e 100644 --- a/xmake/modules/private/utils/batchcmds.lua +++ b/xmake/modules/private/utils/batchcmds.lua @@ -28,6 +28,7 @@ import("core.theme.theme") import("core.tool.linker") import("core.tool.compiler") import("core.language.language") +import("utils.run_script") import("utils.progress", {alias = "progress_utils"}) import("utils.binary.rpath", {alias = "rpath_utils"}) @@ -121,6 +122,22 @@ function _runcmd_vexecv(cmd, opt) end end +-- run command: lua +function _runcmd_lua(cmd, opt) + if cmd.script then + if opt.dryrun then + print(os.args(table.join("xmake", "lua", cmd.script, cmd.argv))) + else + vprint(os.args(table.join("xmake", "lua", cmd.script, cmd.argv))) + local runopt = table.clone(cmd.opt) or {} + runopt.arguments = cmd.argv + -- it will run in a separate native thread, which will not block other coroutine jobs + runopt.thread = true + run_script(cmd.script, runopt) + end + end +end + -- run command: os.mkdir function _runcmd_mkdir(cmd, opt) local dir = cmd.dir @@ -214,6 +231,7 @@ function _runcmd(cmd, opt) vrunv = _runcmd_vrunv, execv = _runcmd_execv, vexecv = _runcmd_vexecv, + lua = _runcmd_lua, mkdir = _runcmd_mkdir, rmdir = _runcmd_rmdir, cd = _runcmd_cd, @@ -271,6 +289,11 @@ function batchcmds:vexecv(program, argv, opt) table.insert(self:cmds(), {kind = "vexecv", program = program, argv = argv, opt = opt}) end +-- add command: run lua script file, command or module +function batchcmds:lua(script, argv, opt) + table.insert(self:cmds(), {kind = "lua", script = script, argv = argv, opt = opt}) +end + -- add command: compiler.compile function batchcmds:compile(sourcefiles, objectfile, opt) diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index 709580f1b..0394ccb6e 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -170,11 +170,19 @@ function main(script, opt) local curdir = opt.curdir or os.workingdir() local oldir = os.cd(curdir) if opt.thread then + local argv + for _, arg in ipairs(opt.arguments) do + argv = argv or {} + if path.instance_of(arg) then + arg = tostring(arg) + end + table.insert(argv, arg) + end local thread_opt = { curdir = curdir, command = opt.command, deserialize = opt.deserialize, - arguments = opt.arguments, + arguments = argv, verbose = opt.verbose, diagnosis = opt.diagnosis } diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 9bed0f658..5373d2093 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -38,7 +38,7 @@ rule("utils.bin2c") -- add commands batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin) batchcmds:mkdir(headerdir) - local argv = {"lua", "private.utils.bin2c", "-i", path(sourcefile_bin), "-o", path(headerfile)} + local argv = {"-i", path(sourcefile_bin), "-o", path(headerfile)} local linewidth = target:extraconf("rules", "utils.bin2c", "linewidth") if linewidth then table.insert(argv, "-w") @@ -48,7 +48,7 @@ rule("utils.bin2c") if nozeroend then table.insert(argv, "--nozeroend") end - batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) + batchcmds:lua("private.utils.bin2c", argv) -- add deps batchcmds:add_depfiles(sourcefile_bin) -- cgit v1.3.1 From 9b446fb15e4c91cb6687cf904e4d39f3ce30637d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 4 Sep 2025 23:04:43 +0800 Subject: improve batchcmds:lua --- xmake/modules/private/utils/batchcmds.lua | 38 ++++++++++++++++++++++++------- xmake/modules/utils/run_script.lua | 22 ++++++++++++++---- xmake/rules/utils/bin2c/xmake.lua | 2 +- 3 files changed, 49 insertions(+), 13 deletions(-) (limited to 'xmake/modules/utils/run_script.lua') diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua index 544c94c2e..268f34154 100644 --- a/xmake/modules/private/utils/batchcmds.lua +++ b/xmake/modules/private/utils/batchcmds.lua @@ -103,9 +103,7 @@ end -- run command: os.execv function _runcmd_execv(cmd, opt) if cmd.program then - if opt.dryrun then - print(os.args(table.join(cmd.program, cmd.argv))) - else + if not opt.dryrun then os.execv(cmd.program, cmd.argv, cmd.opt) end end @@ -115,7 +113,7 @@ end function _runcmd_vexecv(cmd, opt) if cmd.program then if opt.dryrun then - print(os.args(table.join(cmd.program, cmd.argv))) + vprint(os.args(table.join(cmd.program, cmd.argv))) else os.vexecv(cmd.program, cmd.argv, cmd.opt) end @@ -125,12 +123,30 @@ end -- run command: lua function _runcmd_lua(cmd, opt) if cmd.script then - if opt.dryrun then - print(os.args(table.join("xmake", "lua", cmd.script, cmd.argv))) - else - vprint(os.args(table.join("xmake", "lua", cmd.script, cmd.argv))) + if not opt.dryrun then local runopt = table.clone(cmd.opt) or {} runopt.arguments = cmd.argv + runopt.quiet = true + -- it will run in a separate native thread, which will not block other coroutine jobs + runopt.thread = true + run_script(cmd.script, runopt) + end + end +end + +-- run command: vlua +function _runcmd_vlua(cmd, opt) + if cmd.script then + vprint(os.args(table.join("xmake", "lua", cmd.script, cmd.argv))) + if not opt.dryrun then + local runopt = table.clone(cmd.opt) or {} + runopt.arguments = cmd.argv + if option.get("diagnosis") then + runopt.verbose = true + runopt.diagnosis = true + else + runopt.quiet = not option.get("verbose") + end -- it will run in a separate native thread, which will not block other coroutine jobs runopt.thread = true run_script(cmd.script, runopt) @@ -232,6 +248,7 @@ function _runcmd(cmd, opt) execv = _runcmd_execv, vexecv = _runcmd_vexecv, lua = _runcmd_lua, + vlua = _runcmd_vlua, mkdir = _runcmd_mkdir, rmdir = _runcmd_rmdir, cd = _runcmd_cd, @@ -294,6 +311,11 @@ function batchcmds:lua(script, argv, opt) table.insert(self:cmds(), {kind = "lua", script = script, argv = argv, opt = opt}) end +-- add command: run lua script file, command or module +function batchcmds:vlua(script, argv, opt) + table.insert(self:cmds(), {kind = "vlua", script = script, argv = argv, opt = opt}) +end + -- add command: compiler.compile function batchcmds:compile(sourcefiles, objectfile, opt) diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index 0394ccb6e..de625119f 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -19,8 +19,9 @@ -- -- imports -import("core.sandbox.module") +import("core.base.option") import("core.base.thread") +import("core.sandbox.module") -- print verbose log function _print_vlog(script_type, script_name, args, opt) @@ -142,11 +143,25 @@ function _get_args(opt) end function _run(script, opt) + opt = opt or {} + + if opt.quiet then + option.save() + option.set("quiet", true, {force = true}) + end + + local curdir = opt.curdir or os.workingdir() + local oldir = os.cd(curdir) if opt.command then _run_commanad(script, _get_args(opt), opt) else _run_script(script, _get_args(opt), opt) end + os.cd(oldir) + + if opt.quiet then + option.restore() + end end function _run_in_thread(script, opt) @@ -163,12 +178,11 @@ end -- - deserialize deserialize arguments starts with given prefix -- - arguments the script arguments -- - thread run script in a new native thread +-- - quiet enable quiet output -- - verbose enable verbose output -- - diagnosis enable diagnosis output function main(script, opt) opt = opt or {} - local curdir = opt.curdir or os.workingdir() - local oldir = os.cd(curdir) if opt.thread then local argv for _, arg in ipairs(opt.arguments) do @@ -183,6 +197,7 @@ function main(script, opt) command = opt.command, deserialize = opt.deserialize, arguments = argv, + quiet = opt.quiet, verbose = opt.verbose, diagnosis = opt.diagnosis } @@ -191,5 +206,4 @@ function main(script, opt) else _run(script, opt) end - os.cd(oldir) end diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 5373d2093..082e8fb5b 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -48,7 +48,7 @@ rule("utils.bin2c") if nozeroend then table.insert(argv, "--nozeroend") end - batchcmds:lua("private.utils.bin2c", argv) + batchcmds:vlua("private.utils.bin2c", argv) -- add deps batchcmds:add_depfiles(sourcefile_bin) -- cgit v1.3.1