diff options
Diffstat (limited to 'xmake/core/base/task.lua')
| -rw-r--r-- | xmake/core/base/task.lua | 63 |
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 |
