summaryrefslogtreecommitdiff
path: root/xmake/core/base/task.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-15 17:57:22 +0800
committerGitHub <[email protected]>2026-08-15 17:57:22 +0800
commit0a32ec18d737259052271fa3be5cfdb50dbd1d15 (patch)
tree50be742aed502e6f5432ff841766bec4e38ff16d /xmake/core/base/task.lua
parent069474769dcfb01898f2c7066c1bf71d5da79125 (diff)
parent67ffcd8a481a5c6c51da8044bfe1ebed980b1e56 (diff)
Merge pull request #7696 from xmake-io/addon
Add addon support for plugins
Diffstat (limited to 'xmake/core/base/task.lua')
-rw-r--r--xmake/core/base/task.lua63
1 files changed, 55 insertions, 8 deletions
diff --git a/xmake/core/base/task.lua b/xmake/core/base/task.lua
index d6f581cf9..2cd1fa58a 100644
--- a/xmake/core/base/task.lua
+++ b/xmake/core/base/task.lua
@@ -28,6 +28,7 @@ local string = require("base/string")
local global = require("base/global")
local hashset = require("base/hashset")
local interpreter = require("base/interpreter")
+local addon = require("package/addon")
local sandbox = require("sandbox/sandbox")
local config = require("project/config")
local sandbox_os = require("sandbox/modules/os")
@@ -81,13 +82,20 @@ end
-- the directories of tasks
function task._directories()
- local dirs = {
- path.join(global.directory(), "plugins"),
- path.join(os.programdir(), "plugins"),
- path.join(os.programdir(), "actions")}
- local plugindirs = os.getenv("XMAKE_PLUGIN_DIRS")
- if plugindirs then
- table.insert(dirs, 1, plugindirs)
+ local dirs = task._DIRECTORIES
+ if dirs == nil then
+ dirs = {
+ path.join(global.directory(), "plugins"),
+ path.join(os.programdir(), "plugins"),
+ path.join(os.programdir(), "actions")}
+
+ -- add the plugins of the installed addons, e.g. ~/.xmake/addons/<name>/<version>/plugins
+ --
+ -- we get them from the addons registry file directly,
+ -- so we do not need to scan the whole addons directory on startup
+ --
+ table.join2(dirs, addon.payloads("plugins"))
+ task._DIRECTORIES = dirs
end
return dirs
end
@@ -391,6 +399,39 @@ function task.new(name, info)
return instance
end
+-- is the given plugin conflicting with the loaded one?
+--
+-- the plugins are not namespaced, so we need to report the conflicts of the addons,
+-- otherwise we do not know which plugin will be run
+--
+-- @param taskname the task name
+-- @param taskfile the task file of the loaded plugin, it will be nil if it's the first one
+-- @param filepath the task file of the plugin which we are loading
+--
+function task._is_conflicting(taskname, taskfile, filepath)
+ if not taskfile then
+ return false
+ end
+
+ -- we only report it if one of them comes from an addon, the builtin plugins
+ -- and the plugins in the global directory are always overridable
+ local addondir = path.absolute(addon.installdir())
+ if not path.absolute(taskfile):startswith(addondir) and not path.absolute(filepath):startswith(addondir) then
+ return false
+ end
+
+ -- @note we cannot raise errors here, otherwise all the commands will be broken,
+ -- and the user cannot even remove the conflicting addons
+ utils.warning("plugin(%s) conflicts, we will use the first one!\n -> %s\n -> %s", taskname, taskfile, filepath)
+ return true
+end
+
+-- clear the loaded tasks, e.g. some addons may be installed just now
+function task.clear()
+ task._TASKS = nil
+ task._DIRECTORIES = nil
+end
+
-- get all registered tasks
--
-- @return the tasks table {name = task, ...}
@@ -402,6 +443,7 @@ function task.tasks()
-- load tasks
local tasks = {}
+ local taskfiles = {}
local dirs = task._directories()
for _, dir in ipairs(dirs) do
local files = os.files(path.join(dir, "*", "xmake.lua"))
@@ -409,7 +451,12 @@ function task.tasks()
for _, filepath in ipairs(files) do
local results, errors = task._load(filepath)
if results then
- table.join2(tasks, results)
+ for taskname, taskinfo in pairs(results) do
+ if not task._is_conflicting(taskname, taskfiles[taskname], filepath) then
+ taskfiles[taskname] = filepath
+ tasks[taskname] = taskinfo
+ end
+ end
else
os.raise(errors)
end