diff options
| author | ruki <[email protected]> | 2020-02-03 22:51:06 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2020-02-07 22:45:56 +0800 |
| commit | cf9970fddd580f8b9bb8ed25d6d9cfa67a607b69 (patch) | |
| tree | 57dda8e994431a59f96f44fec83d416fb4db0db6 | |
| parent | ccfe7ed01bd603f4435ce6463ecf267f49ddd6fe (diff) | |
improve to open process and support pipe
| -rw-r--r-- | core/src/xmake/process/open.c | 32 | ||||
| -rw-r--r-- | core/src/xmake/process/openv.c | 46 | ||||
| -rw-r--r-- | tests/modules/process/test.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/build/cleaner.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/build/statistics.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/io.lua | 42 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 14 | ||||
| -rw-r--r-- | xmake/core/base/pipe.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/process.lua | 56 |
9 files changed, 156 insertions, 42 deletions
diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c index 45892fefd..2f45b5c6f 100644 --- a/core/src/xmake/process/open.c +++ b/core/src/xmake/process/open.c @@ -35,7 +35,9 @@ * implementation */ -// p = process.open(command, {outpath = "", errpath = "", envs = {"PATH=xxx", "XXX=yyy"}}) +/* p = process.open(command, + * {outpath = "", errpath = "", outfile = "", errfile = "", outpipe = "", errpipe = "", envs = {"PATH=xxx", "XXX=yyy"}}) + */ tb_int_t xm_process_open(lua_State* lua) { // check @@ -88,6 +90,24 @@ tb_int_t xm_process_open(lua_State* lua) lua_pop(lua, 1); } + // get outpipe + if (!outpath && !outfile) + { + lua_pushstring(lua, "outpipe"); + lua_gettable(lua, 3); + outpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1); + lua_pop(lua, 1); + } + + // get errpipe + if (!errpath && !errfile) + { + lua_pushstring(lua, "errpipe"); + lua_gettable(lua, 3); + errpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1); + lua_pop(lua, 1); + } + // get environments lua_pushstring(lua, "envs"); lua_gettable(lua, 2); @@ -148,6 +168,11 @@ tb_int_t xm_process_open(lua_State* lua) attr.outtype = TB_PROCESS_REDIRECT_TYPE_FILE; } } + else if (outpipe) + { + attr.outpipe = outpipe; + attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE; + } // redirect stderr? if (errpath) @@ -166,6 +191,11 @@ tb_int_t xm_process_open(lua_State* lua) attr.errtype = TB_PROCESS_REDIRECT_TYPE_FILE; } } + else if (errpipe) + { + attr.errpipe = errpipe; + attr.errtype = TB_PROCESS_REDIRECT_TYPE_PIPE; + } // set the new environments if (envn > 0) attr.envp = envs; diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c index 5e0af8d9c..69557aa69 100644 --- a/core/src/xmake/process/openv.c +++ b/core/src/xmake/process/openv.c @@ -35,7 +35,9 @@ * implementation */ -// p = process.openv(shellname, argv, {outpath = "", errpath = "", outfile = , errfile = , envs = {"PATH=xxx", "XXX=yyy"}) +/* p = process.openv(shellname, argv, + * {outpath = "", errpath = "", outfile = , errfile = , outpipe = , errpipe, envs = {"PATH=xxx", "XXX=yyy"}) + */ tb_int_t xm_process_openv(lua_State* lua) { // check @@ -92,12 +94,14 @@ tb_int_t xm_process_openv(lua_State* lua) tb_process_attr_t attr = {0}; // get option arguments - tb_size_t envn = 0; - tb_char_t const* envs[256] = {0}; - tb_char_t const* outpath = tb_null; - tb_char_t const* errpath = tb_null; - xm_io_file_t* outfile = tb_null; - xm_io_file_t* errfile = tb_null; + tb_size_t envn = 0; + tb_char_t const* envs[256] = {0}; + tb_char_t const* outpath = tb_null; + tb_char_t const* errpath = tb_null; + xm_io_file_t* outfile = tb_null; + xm_io_file_t* errfile = tb_null; + tb_pipe_file_ref_t outpipe = tb_null; + tb_pipe_file_ref_t errpipe = tb_null; if (lua_istable(lua, 3)) { // get outpath @@ -130,6 +134,24 @@ tb_int_t xm_process_openv(lua_State* lua) lua_pop(lua, 1); } + // get outpipe + if (!outpath && !outfile) + { + lua_pushstring(lua, "outpipe"); + lua_gettable(lua, 3); + outpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1); + lua_pop(lua, 1); + } + + // get errpipe + if (!errpath && !errfile) + { + lua_pushstring(lua, "errpipe"); + lua_gettable(lua, 3); + errpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1); + lua_pop(lua, 1); + } + // get environments lua_pushstring(lua, "envs"); lua_gettable(lua, 3); @@ -190,6 +212,11 @@ tb_int_t xm_process_openv(lua_State* lua) attr.outtype = TB_PROCESS_REDIRECT_TYPE_FILE; } } + else if (outpipe) + { + attr.outpipe = outpipe; + attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE; + } // redirect stderr? if (errpath) @@ -208,6 +235,11 @@ tb_int_t xm_process_openv(lua_State* lua) attr.errtype = TB_PROCESS_REDIRECT_TYPE_FILE; } } + else if (errpipe) + { + attr.errpipe = errpipe; + attr.errtype = TB_PROCESS_REDIRECT_TYPE_PIPE; + } // set the new environments if (envn > 0) attr.envp = envs; diff --git a/tests/modules/process/test.lua b/tests/modules/process/test.lua index 24846fd02..8e9e45bd8 100644 --- a/tests/modules/process/test.lua +++ b/tests/modules/process/test.lua @@ -7,7 +7,7 @@ function test_single_process(t) local stdout = os.tmpfile() local stderr = os.tmpfile() for i = 1, 2 do - local proc = process.open("echo -n awd", {outpath = stdout, errpath = stderr}) + local proc = process.open("echo -n awd", {stdout = stdout, stderr = stderr}) proc:wait(inftimeout) proc:close() t:are_equal(io.readfile(stdout), "awd") diff --git a/xmake/actions/build/cleaner.lua b/xmake/actions/build/cleaner.lua index f128e7a7d..7d629b978 100644 --- a/xmake/actions/build/cleaner.lua +++ b/xmake/actions/build/cleaner.lua @@ -53,7 +53,7 @@ function cleanup() try { function () - local proc = process.openv("xmake", argv, {outpath = path.join(os.tmpdir(), "cleaner.log")}) + local proc = process.openv("xmake", argv, {stdout = path.join(os.tmpdir(), "cleaner.log")}) if proc ~= nil then proc:close() end diff --git a/xmake/actions/build/statistics.lua b/xmake/actions/build/statistics.lua index 996295de6..1e29cb666 100644 --- a/xmake/actions/build/statistics.lua +++ b/xmake/actions/build/statistics.lua @@ -88,7 +88,7 @@ function post() try { function () - local proc = process.openv("xmake", argv, {outpath = path.join(os.tmpdir(), projectname .. ".stats.log")}) + local proc = process.openv("xmake", argv, {stdout = path.join(os.tmpdir(), projectname .. ".stats.log")}) if proc ~= nil then proc:close() end diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index d950c07b0..ee1553d2d 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -64,7 +64,7 @@ function _file:close() end -- close file - ok, errors = io.file_close(self._FILE) + ok, errors = io.file_close(self:cdata()) if ok then self._FILE = nil end @@ -106,7 +106,7 @@ end -- gc(file) function _file:__gc() - if self._FILE and io.file_close(self._FILE) then + if self:cdata() and io.file_close(self:cdata()) then self._FILE = nil end end @@ -116,6 +116,11 @@ function _file:__len() return _file.size(self) end +-- get cdata +function _file:cdata() + return self._FILE +end + -- get file rawfd function _file:rawfd() @@ -126,7 +131,7 @@ function _file:rawfd() end -- get file rawfd - local result, errors = io.file_rawfd(self._FILE) + local result, errors = io.file_rawfd(self:cdata()) if not result and errors then errors = string.format("%s: %s", self, errors) end @@ -143,7 +148,7 @@ function _file:size() end -- get file size - local result, errors = io.file_size(self._FILE) + local result, errors = io.file_size(self:cdata()) if not result and errors then errors = string.format("%s: %s", self, errors) end @@ -161,7 +166,7 @@ function _file:read(fmt, opt) -- read file opt = opt or {} - local result, errors = io.file_read(self._FILE, fmt, opt.continuation) + local result, errors = io.file_read(self:cdata(), fmt, opt.continuation) if errors then errors = string.format("%s: %s", self, errors) end @@ -178,7 +183,7 @@ function _file:write(...) end -- write file - ok, errors = io.file_write(self._FILE, ...) + ok, errors = io.file_write(self:cdata(), ...) if not ok and errors then errors = string.format("%s: %s", self, errors) end @@ -195,7 +200,7 @@ function _file:seek(whence, offset) end -- seek file - local result, errors = io.file_seek(self._FILE, whence, offset) + local result, errors = io.file_seek(self:cdata(), whence, offset) if not result and errors then errors = string.format("%s: %s", self, errors) end @@ -212,7 +217,7 @@ function _file:flush() end -- flush file - ok, errors = io.file_flush(self._FILE) + ok, errors = io.file_flush(self:cdata()) if not ok and errors then errors = string.format("%s: %s", self, errors) end @@ -229,7 +234,7 @@ function _file:isatty() end -- is a tty? - ok, errors = io.file_isatty(self._FILE) + ok, errors = io.file_isatty(self:cdata()) if ok == nil and errors then errors = string.format("%s: %s", self, errors) end @@ -238,7 +243,7 @@ end -- ensure the file is opened function _file:_ensure_opened() - if not self._FILE then + if not self:cdata() then return false, string.format("%s: has been closed!", self) end return true @@ -308,6 +313,11 @@ function _filelock:path() return self._PATH end +-- get the cdata +function _filelock:cdata() + return self._LOCK +end + -- is locked? function _filelock:islocked() return self._LOCKED_NUM > 0 @@ -328,7 +338,7 @@ function _filelock:lock(opt) end -- lock it - if self._LOCKED_NUM > 0 or io.filelock_lock(self._LOCK, opt) then + if self._LOCKED_NUM > 0 or io.filelock_lock(self:cdata(), opt) then self._LOCKED_NUM = self._LOCKED_NUM + 1 return true else @@ -351,7 +361,7 @@ function _filelock:trylock(opt) end -- try lock it - if self._LOCKED_NUM > 0 or io.filelock_trylock(self._LOCK, opt) then + if self._LOCKED_NUM > 0 or io.filelock_trylock(self:cdata(), opt) then self._LOCKED_NUM = self._LOCKED_NUM + 1 return true else @@ -369,7 +379,7 @@ function _filelock:unlock(opt) end -- unlock it - if self._LOCKED_NUM > 1 or (self._LOCKED_NUM > 0 and io.filelock_unlock(self._LOCK)) then + if self._LOCKED_NUM > 1 or (self._LOCKED_NUM > 0 and io.filelock_unlock(self:cdata())) then if self._LOCKED_NUM > 0 then self._LOCKED_NUM = self._LOCKED_NUM - 1 else @@ -391,7 +401,7 @@ function _filelock:close() end -- close it - ok = io.filelock_close(self._LOCK) + ok = io.filelock_close(self:cdata()) if ok then self._LOCK = nil self._LOCKED_NUM = 0 @@ -401,7 +411,7 @@ end -- ensure the file is opened function _filelock:_ensure_opened() - if not self._LOCK then + if not self:cdata() then return false, string.format("%s: has been closed!", self) end return true @@ -424,7 +434,7 @@ end -- gc(filelock) function _filelock:__gc() - if self._LOCK and io.filelock_close(self._LOCK) then + if self:cdata() and io.filelock_close(self:cdata()) then self._LOCK = nil self._LOCKED_NUM = 0 end diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 4a31db46c..46a0ad1a1 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -608,7 +608,7 @@ end -- @param program "clang", "xcrun -sdk macosx clang", "~/dir/test\ xxx/clang" -- filename "clang", "xcrun"", "~/dir/test\ xxx/clang" -- @param argv the arguments --- @param opt the options, e.g. {wildcards = false, stdout = outfile, stderr = errfile, +-- @param opt the options, e.g. {wildcards = false, stdout = filepath/file/pipe, stderr = filepath/file/pipe, -- envs = {PATH = "xxx;xx", CFLAGS = "xx"}} -- function os.execv(program, argv, opt) @@ -651,17 +651,7 @@ function os.execv(program, argv, opt) end -- init open options - local openopt = {envs = envs} - if type(opt.stdout) == "table" then - openopt.outfile = opt.stdout._FILE - else - openopt.outpath = opt.stdout - end - if type(opt.stderr) == "table" then - openopt.errfile = opt.stderr._FILE - else - openopt.errpath = opt.stderr - end + local openopt = {envs = envs, stdout = opt.stdout, stderr = opt.stderr} -- open command local ok = -1 diff --git a/xmake/core/base/pipe.lua b/xmake/core/base/pipe.lua index be798a606..3252ef5e4 100644 --- a/xmake/core/base/pipe.lua +++ b/xmake/core/base/pipe.lua @@ -48,7 +48,7 @@ function _instance:name() return self._NAME end --- get poller object type, poller.OT_instance +-- get poller object type, poller.OT_PIPE function _instance:otype() return 2 end diff --git a/xmake/core/base/process.lua b/xmake/core/base/process.lua index 99f756fdc..aa442f6d7 100644 --- a/xmake/core/base/process.lua +++ b/xmake/core/base/process.lua @@ -140,11 +140,37 @@ end -- open a subprocess -- -- @param command the process command --- @param opt the option arguments, e.g. {outpath = "", errpath = "", envs = {"PATH=xxx", "XXX=yyy"}}) +-- @param opt the option arguments, e.g. {stdout = filepath/file/pipe, stderr = filepath/file/pipe, envs = {"PATH=xxx", "XXX=yyy"}}) -- -- @return the subprocess -- function process.open(command, opt) + + -- get stdout and pass to subprocess + local stdout = opt.stdout + if type(stdout) == "string" then + opt.outpath = stdout + elseif type(stdout) == "table" then + if stdout.otype and stdout:otype() == 2 then + opt.outpipe = stdout:cdata() + else + opt.outfile = stdout:cdata() + end + end + + -- get stderr and pass to subprocess + local stderr = opt.stderr + if type(stderr) == "string" then + opt.errpath = stderr + elseif type(stderr) == "table" then + if stderr.otype and stderr:otype() == 2 then + opt.errpipe = stderr:cdata() + else + opt.errfile = stderr:cdata() + end + end + + -- open subprocess local proc = process._open(command, opt) if proc then return _subprocess.new(path.filename(command:split(' ', {plain = true})[1]), proc) @@ -157,11 +183,37 @@ end -- -- @param shellname the shell name -- @param argv the arguments list --- @param opt the option arguments, e.g. {outpath = "", errpath = "", envs = {"PATH=xxx", "XXX=yyy"}}) +-- @param opt the option arguments, e.g. {stdout = filepath/file/pipe, stderr = filepath/file/pipe, envs = {"PATH=xxx", "XXX=yyy"}}) -- -- @return the subprocess -- function process.openv(shellname, argv, opt) + + -- get stdout and pass to subprocess + local stdout = opt.stdout + if type(stdout) == "string" then + opt.outpath = stdout + elseif type(stdout) == "table" then + if stdout.otype and stdout:otype() == 2 then + opt.outpipe = stdout:cdata() + else + opt.outfile = stdout:cdata() + end + end + + -- get stderr and pass to subprocess + local stderr = opt.stderr + if type(stderr) == "string" then + opt.errpath = stderr + elseif type(stderr) == "table" then + if stderr.otype and stderr:otype() == 2 then + opt.errpipe = stderr:cdata() + else + opt.errfile = stderr:cdata() + end + end + + -- open subprocess local proc = process._openv(shellname, argv, opt) if proc then return _subprocess.new(path.filename(shellname), proc) |
