summaryrefslogtreecommitdiff
path: root/xmake
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-11 23:45:05 +0800
committerruki <[email protected]>2026-08-11 23:45:05 +0800
commit7ffcc9f8e2a98d63f7f6880b9a3e4553439583c6 (patch)
treef2bf7c4e0e9806fd157cc3243a45f691fd282988 /xmake
parent9e6abef8b0a26d7098d79749dd68b5a2590512c4 (diff)
add global modules and rewrite addon tests
Diffstat (limited to 'xmake')
-rw-r--r--xmake/actions/addon/main.lua9
-rw-r--r--xmake/core/package/addon.lua41
-rw-r--r--xmake/core/sandbox/modules/import/core/sandbox/module.lua37
-rw-r--r--xmake/modules/private/action/require/impl/actions/install.lua3
4 files changed, 62 insertions, 28 deletions
diff --git a/xmake/actions/addon/main.lua b/xmake/actions/addon/main.lua
index 878b1712d..481b9334b 100644
--- a/xmake/actions/addon/main.lua
+++ b/xmake/actions/addon/main.lua
@@ -118,12 +118,19 @@ function _install_from_local(dir, name)
{
function ()
addon.register(name, LOCALVERSION, manifest and {
- description = manifest.description, deps = #manifest.deps > 0 and manifest.deps or nil})
+ description = manifest.description,
+ deps = #manifest.deps > 0 and manifest.deps or nil,
+ globalmodules = #manifest.globalmodules > 0 and manifest.globalmodules or nil})
end,
catch
{
function (errors)
os.tryrm(dstdir)
+ -- we need to remove the addon directory too if no other version is installed
+ local addondir = path.directory(dstdir)
+ if #os.filedirs(path.join(addondir, "*")) == 0 then
+ os.tryrm(addondir)
+ end
raise(errors)
end
}
diff --git a/xmake/core/package/addon.lua b/xmake/core/package/addon.lua
index e5b03b959..1f116bcd4 100644
--- a/xmake/core/package/addon.lua
+++ b/xmake/core/package/addon.lua
@@ -154,16 +154,25 @@ end
-- @return the errors if there are some conflicts
--
function addon._check_conflicts(dirname, addoninfo)
- for _, kind in ipairs({"plugins", "templates"}) do
+ local kindnames = {plugins = "plugin", templates = "template", globalmodules = "global module"}
+ for _, kind in ipairs({"plugins", "templates", "globalmodules"}) do
for _, name in ipairs(addoninfo[kind] or {}) do
for otherdirname, otheraddoninfo in pairs(addon.addons()) do
if otherdirname ~= dirname and table.contains(otheraddoninfo[kind] or {}, name) then
return string.format("%s(%s) conflicts, it has been provided by the addon(%s)!\nplease remove one of them, e.g. xmake addon --remove %s",
- kind == "plugins" and "plugin" or "template", name, otherdirname, otherdirname)
+ kindnames[kind], name, otherdirname, otherdirname)
end
end
end
end
+
+ -- the global modules can also conflict with the builtin ones
+ for _, name in ipairs(addoninfo.globalmodules or {}) do
+ local modulefile = path.join(os.programdir(), "modules", (name:gsub("%.", "/")) .. ".lua")
+ if os.isfile(modulefile) then
+ return string.format("global module(%s) conflicts, it has been provided by xmake!\nplease rename it in the addon manifest.", name)
+ end
+ end
end
-- get the addons which depend on the given addon
@@ -203,6 +212,7 @@ function addon.apis()
, "addon.set_sourcedir"
-- addon.add_xxx
, "addon.add_deps"
+ , "addon.add_globalmodules"
}
}
end
@@ -252,7 +262,8 @@ function addon.manifest(sourcedir)
homepage = addoninfo:get("homepage"),
license = addoninfo:get("license"),
sourcedir = addoninfo:get("sourcedir"),
- deps = table.wrap(addoninfo:get("deps"))}
+ deps = table.wrap(addoninfo:get("deps")),
+ globalmodules = table.wrap(addoninfo:get("globalmodules"))}
end
if not manifest then
return nil, string.format("%s: no addon() scope found!", manifestfile)
@@ -422,6 +433,28 @@ function addon.addondir(name, version)
return path.join(addon.installdir(), dirname, version)
end
+-- get the modules which the installed addons export as the global modules
+--
+-- they are declared in the addon manifest, e.g. add_globalmodules("core.tools.esptool"),
+-- so that they can be imported with their plain names by the internal calls,
+-- e.g. import("core.tools.esptool"), find_tool("esptool")
+--
+-- @return the modules table, e.g. {["core.tools.esptool"] = "~/.xmake/addons/esp32/v1.0.0/modules"}
+--
+function addon.globalmodules()
+ local globalmodules = addon._GLOBALMODULES
+ if globalmodules == nil then
+ globalmodules = {}
+ for dirname, addoninfo in pairs(addon.addons()) do
+ for _, name in ipairs(addoninfo.globalmodules or {}) do
+ globalmodules[name] = path.join(addon.installdir(), dirname, addoninfo.version, "modules")
+ end
+ end
+ addon._GLOBALMODULES = globalmodules
+ end
+ return globalmodules
+end
+
-- get the payload directories of the given kind from all installed addons
--
-- @param kind the payload kind, e.g. "plugins", "rules"
@@ -560,6 +593,7 @@ function addon.register(name, version, opt)
-- recorded whenever this addon has one, so that the repositories can
-- check that the manifest and the package recipe are kept in sync
manifest_deps = opt.manifest_deps,
+ globalmodules = opt.globalmodules,
payloads = addon.payloads_of(addondir),
plugins = addon._plugins_of(addondir),
templates = addon._templates_of(addondir)}
@@ -665,6 +699,7 @@ function addon.clear()
end
addon._ADDONS = {}
addon._MANIFESTS = nil
+ addon._GLOBALMODULES = nil
end
-- return module
diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua
index 3fd2d0fe6..4cf419b44 100644
--- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua
+++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua
@@ -441,28 +441,6 @@ function core_sandbox_module.coredir()
return path.join(os.programdir(), "core/sandbox/modules/import")
end
--- get the module directories for the given addon reference
---
--- they are only used for the addon modules,
--- e.g. import("@addon.esp32.sdkconfig"), import("@self.sdkconfig")
---
-function core_sandbox_module.addon_directories(modulesdir)
- local moduledirs = {modulesdir}
-
- -- add the modules of the addon toolchains, e.g. <addondir>/toolchains/<name>/modules
- -- so that a custom toolchain can bundle its tool modules together
- local toolchainsdir = path.join(path.directory(modulesdir), "toolchains")
- if os.isdir(toolchainsdir) then
- for _, toolchaindir in ipairs(os.dirs(path.join(toolchainsdir, "*"))) do
- local dir = path.join(toolchaindir, "modules")
- if os.isdir(dir) then
- table.insert(moduledirs, dir)
- end
- end
- end
- return moduledirs
-end
-
-- add module directories
function core_sandbox_module.add_directories(...)
local moduledirs = core_sandbox_module.directories()
@@ -567,9 +545,22 @@ function core_sandbox_module.import(name, opt)
-- init module directories (disable local packages?)
local modules_directories
if addon_modulesdir then
- modules_directories = core_sandbox_module.addon_directories(addon_modulesdir)
+ -- the addon modules are always resolved from the addon `modules` directory only,
+ -- e.g. import("@addon.esp32.sdkconfig"), import("@self.sdkconfig")
+ modules_directories = {addon_modulesdir}
else
modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories())
+
+ -- an addon can export some modules as the global modules, e.g. add_globalmodules("core.tools.esptool"),
+ -- so that the internal calls can import them with their plain names, e.g. import("core.tools.esptool")
+ --
+ -- @note we only accept the declared names, the other modules of this addon are
+ -- still private and can only be imported with `@addon.`/`@self.`
+ --
+ local globalmodulesdir = addon.globalmodules()[name]
+ if globalmodulesdir then
+ table.insert(modules_directories, rootdir and 2 or 1, globalmodulesdir)
+ end
end
-- load module
diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua
index 8bc51f4b3..c9e09763e 100644
--- a/xmake/modules/private/action/require/impl/actions/install.lua
+++ b/xmake/modules/private/action/require/impl/actions/install.lua
@@ -529,7 +529,8 @@ function main(package)
end
addon.register(package:name(), package:version_str() or "latest",
{description = description, deps = deps,
- manifest_deps = manifest and manifest.deps or nil})
+ manifest_deps = manifest and manifest.deps or nil,
+ globalmodules = manifest and #manifest.globalmodules > 0 and manifest.globalmodules or nil})
end
installed_now = true
end