diff options
| author | ruki <[email protected]> | 2025-11-08 00:01:14 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-11-08 00:01:14 +0800 |
| commit | 041d3951b8817b0bc51d1de39b4c7a5da8ba6e36 (patch) | |
| tree | d911eb795e679a963f9b2e9e40c2a324597bcebb | |
| parent | 88ed1b6ae48753828d4459226b113ac519b4c4e4 (diff) | |
add async support for find_xxx
5 files changed, 384 insertions, 128 deletions
diff --git a/xmake/core/base/private/async_task.lua b/xmake/core/base/private/async_task.lua index 058420e1d..fbb2d8d0b 100644 --- a/xmake/core/base/private/async_task.lua +++ b/xmake/core/base/private/async_task.lua @@ -26,6 +26,7 @@ local os = require("base/os") local utils = require("base/utils") local thread = require("base/thread") local option = require("base/option") +local path = require("base/path") -- the task status local is_stopped = false @@ -40,6 +41,19 @@ local task_mutex = nil local event_pool = {} local sharedata_pool = {} +function async_task._absolute_dirs(searchdirs) + local dirs = {} + if searchdirs then + for _, directory in ipairs(searchdirs) do + local dir = tostring(directory) + if #dir > 0 then + table.insert(dirs, path.absolute(dir)) + end + end + end + return dirs +end + -- get event from pool or create new one function async_task._get_event() local event = table.remove(event_pool) @@ -107,11 +121,31 @@ function async_task._loop(event, queue, mutex, is_stopped, is_diagnosis) local function _runcmd_match(cmd) return os.match(cmd.pattern, cmd.mode) end + local function _runcmd_find_file(cmd) + local find_file = require("sandbox/modules/import/lib/detect/find_file") + return find_file._find_from_directories(cmd.name, cmd.searchdirs or {}, cmd.suffixes or {}) + end + local function _runcmd_find_path(cmd) + local find_path = require("sandbox/modules/import/lib/detect/find_path") + return find_path._find_from_directories(cmd.name, cmd.searchdirs or {}, cmd.suffixes or {}) + end + local function _runcmd_find_directory(cmd) + local find_directory = require("sandbox/modules/import/lib/detect/find_directory") + return find_directory._find_from_directories(cmd.name, cmd.searchdirs or {}, cmd.suffixes or {}) + end + local function _runcmd_find_library(cmd) + local find_library = require("sandbox/modules/import/lib/detect/find_library") + return find_library._find_from_directories(cmd.names or {}, cmd.searchdirs or {}, cmd.kinds or {}, cmd.suffixes or {}, cmd.opt or {}) + end local runops = { cp = _runcmd_cp, rm = _runcmd_rm, rmdir = _runcmd_rmdir, - match = _runcmd_match + match = _runcmd_match, + find_file = _runcmd_find_file, + find_path = _runcmd_find_path, + find_directory = _runcmd_find_directory, + find_library = _runcmd_find_library } local function _runcmd(cmd) @@ -261,7 +295,14 @@ function async_task._post_task(cmd, is_detach, return_data) async_task._put_sharedata(cmd_result) if result and result.ok then if return_data then - return result.data, #result.data + local data = result.data + if type(data) == "table" then + return data, #data + elseif data ~= nil then + return data + else + return nil, 0 + end else return true end @@ -318,6 +359,94 @@ function async_task.match(pattern, mode) return async_task._post_task(cmd, false, true) end +-- find file +function async_task.find_file(name, searchdirs, opt) + opt = opt or {} + local ok, errors = async_task._ensure_started() + if not ok then + return nil, errors + end + local dirs = async_task._absolute_dirs(searchdirs) + local suffixes = {} + if opt.suffixes then + for _, suffix in ipairs(opt.suffixes) do + table.insert(suffixes, tostring(suffix)) + end + end + local cmd = {kind = "find_file", name = tostring(name), searchdirs = dirs, suffixes = suffixes} + return async_task._post_task(cmd, false, true) +end + +-- find path +function async_task.find_path(name, searchdirs, opt) + opt = opt or {} + local ok, errors = async_task._ensure_started() + if not ok then + return nil, errors + end + local dirs = async_task._absolute_dirs(searchdirs) + local suffixes = {} + if opt.suffixes then + for _, suffix in ipairs(opt.suffixes) do + table.insert(suffixes, tostring(suffix)) + end + end + local cmd = {kind = "find_path", name = tostring(name), searchdirs = dirs, suffixes = suffixes} + return async_task._post_task(cmd, false, true) +end + +-- find directory +function async_task.find_directory(name, searchdirs, opt) + opt = opt or {} + local ok, errors = async_task._ensure_started() + if not ok then + return nil, errors + end + local dirs = async_task._absolute_dirs(searchdirs) + local suffixes = {} + if opt.suffixes then + for _, suffix in ipairs(opt.suffixes) do + table.insert(suffixes, tostring(suffix)) + end + end + local cmd = {kind = "find_directory", name = tostring(name), searchdirs = dirs, suffixes = suffixes} + return async_task._post_task(cmd, false, true) +end + +-- find library +function async_task.find_library(names, searchdirs, kinds, opt) + opt = opt or {} + local ok, errors = async_task._ensure_started() + if not ok then + return nil, errors + end + local dirs = async_task._absolute_dirs(searchdirs) + local suffixes = {} + if opt.suffixes then + for _, suffix in ipairs(opt.suffixes) do + table.insert(suffixes, tostring(suffix)) + end + end + local names_list = {} + if names then + if type(names) == "table" then + for _, name in ipairs(names) do + table.insert(names_list, tostring(name)) + end + else + table.insert(names_list, tostring(names)) + end + end + local kinds_list = {} + if kinds then + for _, kind in ipairs(kinds) do + table.insert(kinds_list, tostring(kind)) + end + end + local cmd = {kind = "find_library", names = names_list, searchdirs = dirs, kinds = kinds_list, suffixes = suffixes, opt = {plat = opt.plat}} + return async_task._post_task(cmd, false, true) +end + -- return module: async_task return async_task diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua index 4c6048428..ec737785b 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua @@ -28,6 +28,66 @@ local utils = require("base/utils") local table = require("base/table") local raise = require("sandbox/modules/raise") local vformat = require("sandbox/modules/vformat") +local xmake = require("base/xmake") + +-- expand search paths +function sandbox_lib_detect_find_directory._expand_paths(paths) + local results = {} + for _, _path in ipairs(table.wrap(paths)) do + if type(_path) == "function" then + local ok, result_or_errors = sandbox.load(_path) + if ok then + _path = result_or_errors or "" + else + raise(result_or_errors) + end + else + _path = vformat(_path) + end + for _, _s_path in ipairs(table.wrap(_path)) do + _s_path = tostring(_s_path) + if #_s_path > 0 then + table.insert(results, _s_path) + end + end + end + return results +end + +-- normalize suffixes +function sandbox_lib_detect_find_directory._normalize_suffixes(suffixes) + local results = {} + for _, suffix in ipairs(table.wrap(suffixes)) do + suffix = tostring(suffix) + if #suffix > 0 then + table.insert(results, suffix) + end + end + return results +end + +-- find directory from directories list +function sandbox_lib_detect_find_directory._find_from_directories(name, directories, suffixes) + directories = table.wrap(directories) + suffixes = table.wrap(suffixes) + if #suffixes > 0 then + for _, directory in ipairs(directories) do + for _, suffix in ipairs(suffixes) do + local results = os.dirs(path.join(directory, suffix, name), function (file, isdir) return false end) + if results and #results > 0 then + return results[1] + end + end + end + else + for _, directory in ipairs(directories) do + local results = os.dirs(path.join(directory, name), function (file, isdir) return false end) + if results and #results > 0 then + return results[1] + end + end + end +end -- find directory -- @@ -51,43 +111,17 @@ function sandbox_lib_detect_find_directory.main(name, paths, opt) -- init options opt = opt or {} - -- init paths - paths = table.wrap(paths) + local suffixes = sandbox_lib_detect_find_directory._normalize_suffixes(opt.suffixes) + local directories = sandbox_lib_detect_find_directory._expand_paths(paths) - -- append suffixes to paths - local suffixes = table.wrap(opt.suffixes) - if #suffixes > 0 then - local paths_new = {} - for _, parent in ipairs(paths) do - for _, suffix in ipairs(suffixes) do - table.insert(paths_new, path.join(parent, suffix)) - end - end - paths = paths_new + if opt.async and xmake.in_main_thread() then + local result, _ = os._async_task().find_directory(name, directories, {suffixes = suffixes}) + return result end - -- find file - for _, _path in ipairs(paths) do - - -- format path for builtin variables - if type(_path) == "function" then - local ok, results = sandbox.load(_path) - if ok then - _path = results or "" - else - raise(results) - end - else - _path = vformat(_path) - end - - -- find the first directory - local results = os.dirs(path.join(_path, name), function (file, isdir) return false end) - if results and #results > 0 then - return results[1] - end - end + return sandbox_lib_detect_find_directory._find_from_directories(name, directories, suffixes) end -- return module return sandbox_lib_detect_find_directory + diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua index 8c82d5546..71e580ba1 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua @@ -29,6 +29,72 @@ local table = require("base/table") local profiler = require("base/profiler") local raise = require("sandbox/modules/raise") local vformat = require("sandbox/modules/vformat") +local xmake = require("base/xmake") + +-- expand search paths +function sandbox_lib_detect_find_file._expand_paths(paths) + local results = {} + for _, _path in ipairs(table.wrap(paths)) do + if type(_path) == "function" then + local ok, result_or_errors = sandbox.load(_path) + if ok then + _path = result_or_errors or "" + else + raise(result_or_errors) + end + elseif type(_path) == "string" then + if _path:match("^%$%(env .+%)$") then + _path = path.splitenv(vformat(_path)) + else + _path = vformat(_path) + end + end + for _, _s_path in ipairs(table.wrap(_path)) do + _s_path = tostring(_s_path) + if #_s_path > 0 then + table.insert(results, _s_path) + end + end + end + return results +end + +-- normalize suffixes +function sandbox_lib_detect_find_file._normalize_suffixes(suffixes) + local results = {} + for _, suffix in ipairs(table.wrap(suffixes)) do + suffix = tostring(suffix) + if #suffix > 0 then + table.insert(results, suffix) + end + end + return results +end + +-- find from directories list +function sandbox_lib_detect_find_file._find_from_directories(name, directories, suffixes) + local results + suffixes = table.wrap(suffixes) + directories = table.wrap(directories) + if #suffixes > 0 then + for _, directory in ipairs(directories) do + for _, suffix in ipairs(suffixes) do + local filedir = path.join(directory, suffix) + results = sandbox_lib_detect_find_file._find(filedir, name) + if results then + return results + end + end + end + else + for _, directory in ipairs(directories) do + results = sandbox_lib_detect_find_file._find(directory, name) + if results then + return results + end + end + end +end -- find the given file path or directory function sandbox_lib_detect_find_file._find(filedir, name) @@ -72,48 +138,17 @@ function sandbox_lib_detect_find_file.main(name, paths, opt) -- find file profiler:enter("find_file", name) - local results - local suffixes = table.wrap(opt.suffixes) - for _, _path in ipairs(table.wrap(paths)) do - - -- format path for builtin variables - if type(_path) == "function" then - local ok, result_or_errors = sandbox.load(_path) - if ok then - _path = result_or_errors or "" - else - raise(result_or_errors) - end - elseif type(_path) == "string" then - if _path:match("^%$%(env .+%)$") then - _path = path.splitenv(vformat(_path)) - else - _path = vformat(_path) - end - end + local suffixes = sandbox_lib_detect_find_file._normalize_suffixes(opt.suffixes) + local directories = sandbox_lib_detect_find_file._expand_paths(paths) - for _, _s_path in ipairs(table.wrap(_path)) do - if #_s_path > 0 then - -- find file with suffixes - if #suffixes > 0 then - for _, suffix in ipairs(suffixes) do - local filedir = path.join(_s_path, suffix) - results = sandbox_lib_detect_find_file._find(filedir, name) - if results then - goto found - end - end - else - -- find file in the given path - results = sandbox_lib_detect_find_file._find(_s_path, name) - if results then - goto found - end - end - end - end + -- run in async task? + if opt.async and xmake.in_main_thread() then + local result, _ = os._async_task().find_file(name, directories, {suffixes = suffixes}) + profiler:leave("find_file", name) + return result end -::found:: + + local results = sandbox_lib_detect_find_file._find_from_directories(name, directories, suffixes) profiler:leave("find_file", name) return results end diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua index e072dded1..ab81e88b8 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua @@ -30,8 +30,40 @@ local config = require("project/config") local target = require("project/target") local raise = require("sandbox/modules/raise") local import = require("sandbox/modules/import") +local xmake = require("base/xmake") local find_file = import("lib.detect.find_file") +-- find library from directories list +function sandbox_lib_detect_find_library._find_from_directories(names, directories, kinds, suffixes, opt) + names = table.wrap(names) + directories = table.wrap(directories) + kinds = table.wrap(kinds) + suffixes = table.wrap(suffixes) + if #kinds == 0 then + kinds = {"static", "shared"} + end + opt = opt or {} + local plat = opt.plat + for _, name in ipairs(names) do + for _, kind in ipairs(kinds) do + local filename = target.filename(name, kind, {plat = plat}) + local filepath = find_file._find_from_directories(filename, directories, suffixes) + if plat == "mingw" then + if not filepath and kind == "shared" then + filepath = find_file._find_from_directories(filename .. ".a", directories, suffixes) + end + if not filepath then + filepath = find_file._find_from_directories(target.filename(name, kind, {plat = "windows"}), directories, suffixes) + end + end + if filepath then + local linkname = target.linkname(path.filename(filepath), {plat = plat}) + return {kind = kind, filename = path.filename(filepath), linkdir = path.directory(filepath), link = linkname} + end + end + end +end + -- find library -- -- @param names the library names @@ -56,27 +88,16 @@ function sandbox_lib_detect_find_library.main(names, paths, opt) -- find library file from the given paths opt = opt or {} - local kinds = opt.kind or {"static", "shared"} - for _, name in ipairs(table.wrap(names)) do - for _, kind in ipairs(table.wrap(kinds)) do - local filepath = find_file(target.filename(name, kind, {plat = opt.plat}), paths, opt) - if opt.plat == "mingw" then - if not filepath and kind == "shared" then - -- for implib/mingw, e.g. libxxx.dll.a - filepath = find_file(target.filename(name, kind, {plat = opt.plat}) .. ".a", paths, opt) - end - if not filepath then - -- in order to be compatible with mingw/windows library with .lib - filepath = find_file(target.filename(name, kind, {plat = "windows"}), paths, opt) - end - end - if filepath then - local filename = path.filename(filepath) - local linkname = target.linkname(filename, {plat = opt.plat}) - return {kind = kind, filename = filename, linkdir = path.directory(filepath), link = linkname} - end - end + local directories = find_file._expand_paths(paths) + local suffixes = find_file._normalize_suffixes(opt.suffixes) + local kinds = table.wrap(opt.kind or {"static", "shared"}) + + if opt.async and xmake.in_main_thread() then + local result, _ = os._async_task().find_library(names, directories, kinds, {suffixes = suffixes, plat = opt.plat}) + return result end + + return sandbox_lib_detect_find_library._find_from_directories(names, directories, kinds, suffixes, {plat = opt.plat}) end -- return module diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua index f6a9ec426..cd7413fb7 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua @@ -28,6 +28,43 @@ local table = require("base/table") local profiler = require("base/profiler") local raise = require("sandbox/modules/raise") local vformat = require("sandbox/modules/vformat") +local xmake = require("base/xmake") + +-- expand search paths +function sandbox_lib_detect_find_path._expand_paths(paths) + local results = {} + for _, _path in ipairs(table.wrap(paths)) do + if type(_path) == "function" then + local ok, result_or_errors = sandbox.load(_path) + if ok then + _path = result_or_errors or "" + else + raise(result_or_errors) + end + else + _path = vformat(_path) + end + for _, _s_path in ipairs(table.wrap(_path)) do + _s_path = tostring(_s_path) + if #_s_path > 0 then + table.insert(results, _s_path) + end + end + end + return results +end + +-- normalize suffixes +function sandbox_lib_detect_find_path._normalize_suffixes(suffixes) + local results = {} + for _, suffix in ipairs(table.wrap(suffixes)) do + suffix = tostring(suffix) + if #suffix > 0 then + table.insert(results, suffix) + end + end + return results +end -- find the given file path or directory function sandbox_lib_detect_find_path._find(filedir, name) @@ -52,6 +89,31 @@ function sandbox_lib_detect_find_path._find(filedir, name) end end +-- find from directories list +function sandbox_lib_detect_find_path._find_from_directories(name, directories, suffixes) + local results + suffixes = table.wrap(suffixes) + directories = table.wrap(directories) + if #suffixes > 0 then + for _, directory in ipairs(directories) do + for _, suffix in ipairs(suffixes) do + local filedir = path.join(directory, suffix) + results = sandbox_lib_detect_find_path._find(filedir, name) + if results then + return results + end + end + end + else + for _, directory in ipairs(directories) do + results = sandbox_lib_detect_find_path._find(directory, name) + if results then + return results + end + end + end +end + -- find path -- -- @param name the path name @@ -76,42 +138,17 @@ function sandbox_lib_detect_find_path.main(name, paths, opt) -- init options opt = opt or {} - -- find path - local results profiler:enter("find_path", name) - local suffixes = table.wrap(opt.suffixes) - for _, _path in ipairs(table.wrap(paths)) do + local suffixes = sandbox_lib_detect_find_path._normalize_suffixes(opt.suffixes) + local directories = sandbox_lib_detect_find_path._expand_paths(paths) - -- format path for builtin variables - if type(_path) == "function" then - local ok, result_or_errors = sandbox.load(_path) - if ok then - _path = result_or_errors or "" - else - raise(result_or_errors) - end - else - _path = vformat(_path) - end - - -- find file with suffixes - if #suffixes > 0 then - for _, suffix in ipairs(suffixes) do - local filedir = path.join(_path, suffix) - results = sandbox_lib_detect_find_path._find(filedir, name) - if results then - goto found - end - end - else - -- find file in the given path - results = sandbox_lib_detect_find_path._find(_path, name) - if results then - goto found - end - end + if opt.async and xmake.in_main_thread() then + local result, _ = os._async_task().find_path(name, directories, {suffixes = suffixes}) + profiler:leave("find_path", name) + return result end -::found:: + + local results = sandbox_lib_detect_find_path._find_from_directories(name, directories, suffixes) profiler:leave("find_path", name) return results end |
