summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-11-08 00:01:14 +0800
committerruki <[email protected]>2025-11-08 00:01:14 +0800
commit041d3951b8817b0bc51d1de39b4c7a5da8ba6e36 (patch)
treed911eb795e679a963f9b2e9e40c2a324597bcebb
parent88ed1b6ae48753828d4459226b113ac519b4c4e4 (diff)
add async support for find_xxx
-rw-r--r--xmake/core/base/private/async_task.lua133
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_directory.lua100
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_file.lua115
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_library.lua61
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_path.lua103
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