diff options
| author | ruki <[email protected]> | 2026-08-15 00:04:39 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2026-08-15 00:04:39 +0800 |
| commit | ca9239022e1cba0faf054e8fe2f178a466149b04 (patch) | |
| tree | f646b0c7348435a970bcd28f1cd4dcea2e59dec7 | |
| parent | b13c11f9457e274eeb5e7c51547f619eb4aa6a68 (diff) | |
improve xrepo addon install
| -rw-r--r-- | xmake/actions/addon/main.lua | 29 | ||||
| -rw-r--r-- | xmake/core/package/addon.lua | 7 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 7 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/package/addon.lua | 2 | ||||
| -rw-r--r-- | xmake/modules/private/action/addon/impl/install_addons.lua | 30 | ||||
| -rw-r--r-- | xmake/modules/private/action/addon/impl/xrepo.lua | 54 |
6 files changed, 84 insertions, 45 deletions
diff --git a/xmake/actions/addon/main.lua b/xmake/actions/addon/main.lua index 7183925ea..37923e589 100644 --- a/xmake/actions/addon/main.lua +++ b/xmake/actions/addon/main.lua @@ -23,6 +23,7 @@ import("core.base.option") import("core.package.addon") import("devel.git") import("private.action.addon.impl.install_addons") +import("private.action.addon.impl.xrepo", {alias = "xrepo_addon"}) import("private.action.require.impl.environment") import("private.action.require.impl.search_packages") @@ -50,30 +51,14 @@ function _get_addondir(name, version) return addondir end --- run the given xrepo action for the addons, e.g. install, remove, search -function _xrepo(action, names) - local argv = {"lua", "private.xrepo", action, "--addon"} - -- we need to pass the common options to the sub-process, e.g. -y, -v, -D - if option.get("yes") then - table.insert(argv, "-y") - end - if option.get("verbose") then - table.insert(argv, "-v") - end - if option.get("diagnosis") then - table.insert(argv, "-D") - end - if option.get("force") then - table.insert(argv, "--force") - end - table.join2(argv, names) - os.execv(os.programfile(), argv) -end - -- install an addon from the given repository or the first repository containing it function _install_from_repo(name, reponame) _check_addon_name(name) - _xrepo("install", {reponame and (reponame .. "@" .. name) or name}) + xrepo_addon("install", {reponame and (reponame .. "@" .. name) or name}, + {force = option.get("force"), + -- @note we run it in a temporary directory, this action manages the global addons, + -- so we need not load the project of the current directory again + curdir = os.tmpdir()}) end -- install a single addon from a source directory (as the given name, default to the directory name) @@ -260,7 +245,7 @@ end -- search the addons from the repositories function _search() local patterns = assert(option.get("addons"), "please specify the addon name pattern to be searched!") - _xrepo("search", patterns) + xrepo_addon("search", patterns, {curdir = os.tmpdir()}) end -- collect the installed addons from the addons registry diff --git a/xmake/core/package/addon.lua b/xmake/core/package/addon.lua index 33eb22e03..731c673ab 100644 --- a/xmake/core/package/addon.lua +++ b/xmake/core/package/addon.lua @@ -76,7 +76,7 @@ function addon._save(registry) addon._ADDONS = nil local registryfile = addon._registryfile() -- we need not create an empty registry file if no addons are installed - if next(registry) == nil and not os.isfile(registryfile) then + if table.empty(registry) and not os.isfile(registryfile) then return end local ok, errors = io.save(registryfile, registry) @@ -211,9 +211,10 @@ function addon._unregister(name, version) if version then entry.versions[version] = nil if entry.active == version then - entry.active = next(entry.versions) + -- we need to select the other one deterministically + entry.active = addon.versions(name)[1] end - if next(entry.versions) == nil then + if table.empty(entry.versions) then registry[dirname] = nil end else diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 831f882d4..5c2a12e00 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -259,9 +259,6 @@ end -- do install the addons which this project declares function project._do_install_addons() - if os.getenv("XMAKE_SKIP_ADDONS") then - return true - end -- this project declares nothing? local addonsinfo, errors = addons.load() @@ -297,9 +294,7 @@ function project._do_install_addons() end table.insert(argv, "private.action.addon.impl.install_addons") table.insert(argv, os.projectdir()) - local envs = os.getenvs() - envs.XMAKE_SKIP_ADDONS = "y" - local ok, errors = os.execv(os.programfile(), argv, {curdir = os.tmpdir(), envs = envs}) + local ok, errors = os.execv(os.programfile(), argv, {curdir = os.tmpdir()}) if ok ~= 0 then return false, errors or "install the addons of this project failed!" end diff --git a/xmake/core/sandbox/modules/import/core/package/addon.lua b/xmake/core/sandbox/modules/import/core/package/addon.lua index 89cd60866..dc4740c2e 100644 --- a/xmake/core/sandbox/modules/import/core/package/addon.lua +++ b/xmake/core/sandbox/modules/import/core/package/addon.lua @@ -36,8 +36,6 @@ sandbox_core_package_addon.payloads_of = addon.payloads_of sandbox_core_package_addon.payloadroot = addon.payloadroot sandbox_core_package_addon.addons = addon.addons sandbox_core_package_addon.versions = addon.versions -sandbox_core_package_addon._registry = addon._registry -sandbox_core_package_addon._registryfile = addon._registryfile sandbox_core_package_addon.pin = addon.pin sandbox_core_package_addon.addondir = addon.addondir sandbox_core_package_addon.rescan = addon.rescan diff --git a/xmake/modules/private/action/addon/impl/install_addons.lua b/xmake/modules/private/action/addon/impl/install_addons.lua index 6ece11964..02bb87e2f 100644 --- a/xmake/modules/private/action/addon/impl/install_addons.lua +++ b/xmake/modules/private/action/addon/impl/install_addons.lua @@ -19,9 +19,9 @@ -- -- imports -import("core.base.option") import("core.package.addon") import("core.project.addons") +import("private.action.addon.impl.xrepo", {alias = "xrepo_addon"}) -- the format version of the addons lock file local LOCKVERSION = "1.0" @@ -68,7 +68,17 @@ function _lock_addons(projectdir, addonsinfo) end end lockinfo.__meta__ = {version = LOCKVERSION} - io.save(addons.lockfile(projectdir), lockinfo, {orderkeys = true}) + + -- @note we need to write it deterministically, the key order of a lua table is random, + -- otherwise the lock file would change even if nothing changed, + -- @see xmake/modules/private/action/require/impl/lock_packages.lua + local content = string.serialize(lockinfo, {orderkeys = true}) + local tmpfile = os.tmpfile() + io.writefile(tmpfile, content, {encoding = "binary"}) + + -- and we only write it if the content is different, so we can keep the file time + os.cp(tmpfile, addons.lockfile(projectdir), {copy_if_different = true}) + os.rm(tmpfile) end -- install the addons which the given project declares in its `xmake-addons.lua` @@ -89,7 +99,6 @@ function main(projectdir, opt) -- install them with xrepo, it installs the packages in its own working directory, -- so we need not a project here - local argv = {"lua", "private.xrepo", "install", "--addon"} -- this project declares its own repositories? we pass them to xrepo, -- they are only used by this installation, we do not register them globally @@ -101,26 +110,23 @@ function main(projectdir, opt) file:print("add_repositories(%q)", repo) end file:close() - table.insert(argv, "--includes=" .. rcfile) end - for _, name in ipairs({"yes", "verbose", "diagnosis"}) do - if option.get(name) then - table.insert(argv, "--" .. name) - end - end - table.join2(argv, _get_requires(addonsinfo, locked)) try { function () - os.execv(os.programfile(), argv) + xrepo_addon("install", _get_requires(addonsinfo, locked), {includes = rcfile}) end, finally { - function () + -- @note try() swallows the errors if we do not re-raise them here + function (ok, errors) if rcfile then os.tryrm(rcfile) end + if not ok then + raise(errors) + end end } } diff --git a/xmake/modules/private/action/addon/impl/xrepo.lua b/xmake/modules/private/action/addon/impl/xrepo.lua new file mode 100644 index 000000000..34c1d2632 --- /dev/null +++ b/xmake/modules/private/action/addon/impl/xrepo.lua @@ -0,0 +1,54 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author ruki +-- @file xrepo.lua +-- + +-- imports +import("core.base.option") + +-- run the given xrepo action for the addons +-- +-- @note xrepo installs the packages in its own working project, so it works anywhere, +-- and we need not implement the download/dependencies/confirm logic again +-- +-- @param action the action name, e.g. "install", "search" +-- @param names the addon names, urls or require strings, e.g. {"esp32-devel 1.0.x"} +-- @param opt the options, e.g. {force = true, includes = "/tmp/xxx.lua", curdir = "/tmp"} +-- +function main(action, names, opt) + opt = opt or {} + local argv = {"lua", "private.xrepo", action, "--addon"} + + -- we need to pass the common options to the sub-process, e.g. -y, -v, -D + for _, name in ipairs({"yes", "verbose", "diagnosis"}) do + if option.get(name) then + table.insert(argv, "--" .. name) + end + end + if opt.force then + table.insert(argv, "--force") + end + + -- the extra lua configuration files, e.g. the repositories which a project declares + if opt.includes then + table.insert(argv, "--includes=" .. opt.includes) + end + + table.join2(argv, names) + os.execv(os.programfile(), argv, {curdir = opt.curdir}) +end |
