diff options
Diffstat (limited to 'xmake/core')
| -rw-r--r-- | xmake/core/base/poller.lua | 16 | ||||
| -rw-r--r-- | xmake/core/base/scheduler.lua | 14 | ||||
| -rw-r--r-- | xmake/core/base/task.lua | 36 | ||||
| -rw-r--r-- | xmake/core/package/addon.lua | 13 | ||||
| -rw-r--r-- | xmake/core/package/package.lua | 20 | ||||
| -rw-r--r-- | xmake/core/platform/menu.lua | 2 | ||||
| -rw-r--r-- | xmake/core/project/policy.lua | 6 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/scheduler.lua | 6 |
8 files changed, 80 insertions, 33 deletions
diff --git a/xmake/core/base/poller.lua b/xmake/core/base/poller.lua index bb18dfda4..43c3bea1a 100644 --- a/xmake/core/base/poller.lua +++ b/xmake/core/base/poller.lua @@ -124,7 +124,7 @@ function poller:remove(obj) end -- remove poller object data - self:_pollerdata_set(obj, nil) + self:_pollerdata_set(obj:cdata(), nil) return true end @@ -153,13 +153,15 @@ function poller:wait(timeout) local otype = v[1] local cdata = v[2] local events = v[3] - local pollerdata = self:_pollerdata(cdata) - if not pollerdata then - return -1, string.format("no object data for cdata(%s)!", cdata) + -- this object may have been removed from the poller while its event + -- was already collected, e.g. a pending overlapped io on windows, + -- we just drop it, it has no owner any more, @see poller:remove() + local pollerdata = self:_pollerdata(cdata) + if pollerdata then + local obj = pollerdata[1] + assert(obj and obj:otype() == otype and obj:cdata() == cdata) + table.insert(results, {obj, events, pollerdata[2]}) end - local obj = pollerdata[1] - assert(obj and obj:otype() == otype and obj:cdata() == cdata) - table.insert(results, {obj, events, pollerdata[2]}) end end return count, results diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index a59c38207..4ae8d74e0 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -304,9 +304,17 @@ end function scheduler:_poller_events_cb(obj, events) -- get poller object data + -- + -- the object may have been cancelled while its event was already queued, + -- e.g. a process which exits right after we stopped waiting for it, + -- @see scheduler:poller_cancel() + -- + -- such an event has no owner any more, we just drop it: it is not an + -- error of the scheduler and it must not abort the whole loop local pollerdata = self:_poller_data(obj) if not pollerdata then - return false, string.format("%s: cannot get poller data!", obj) + utils.dprint("%s: drop the event(%d), it has been cancelled!", obj, events) + return true end -- is process/fwatcher object? @@ -1068,6 +1076,10 @@ function scheduler:poller_waitproc(obj, timeout) running:waitobj_set(obj) -- wait + -- + -- @note we keep this process in the poller if it is timeout, so its exit status + -- is still saved as a pending status when it exits later, and the next wait + -- returns it immediately, @see scheduler:_poller_events_cb() local ok = self:co_suspend() return ok, pollerdata.object_event end diff --git a/xmake/core/base/task.lua b/xmake/core/base/task.lua index 2cd1fa58a..2b3788603 100644 --- a/xmake/core/base/task.lua +++ b/xmake/core/base/task.lua @@ -24,6 +24,7 @@ local task = task or {} -- load modules local os = require("base/os") local table = require("base/table") +local utils = require("base/utils") local string = require("base/string") local global = require("base/global") local hashset = require("base/hashset") @@ -84,17 +85,18 @@ end function task._directories() 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 + -- add the plugins of the installed addons first, 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")) + -- @note the first one wins, so an addon is able to take over a deprecated + -- builtin plugin, e.g. `xmake format` + -- + dirs = addon.payloads("plugins") + table.insert(dirs, path.join(global.directory(), "plugins")) + table.insert(dirs, path.join(os.programdir(), "plugins")) + table.insert(dirs, path.join(os.programdir(), "actions")) task._DIRECTORIES = dirs end return dirs @@ -401,8 +403,9 @@ 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 +-- the plugins are not namespaced, so the first one always wins, @see task._directories(), +-- but 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 @@ -413,16 +416,15 @@ function task._is_conflicting(taskname, taskfile, filepath) 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 - + -- we only report it if both of them come from the addons, taking over a builtin + -- plugin is expected, e.g. `xmake format` has been moved to an addon + -- -- @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) + local addondir = path.absolute(addon.installdir()) + if path.absolute(taskfile):startswith(addondir) and path.absolute(filepath):startswith(addondir) then + utils.warning("plugin(%s) conflicts, we will use the first one!\n -> %s\n -> %s", taskname, taskfile, filepath) + end return true end diff --git a/xmake/core/package/addon.lua b/xmake/core/package/addon.lua index e35a58317..d6798f56f 100644 --- a/xmake/core/package/addon.lua +++ b/xmake/core/package/addon.lua @@ -168,12 +168,19 @@ function addon._check_conflicts(dirname, addoninfo) end -- the global modules can also conflict with the builtin and the user modules + -- + -- @note the `core.*` modules are in the core directory of the sandbox, + -- they are not in `<programdir>/modules`, + -- @see core/sandbox/modules/import/core/sandbox/module.lua + local moduledirs = {path.join(os.programdir(), "modules"), + path.join(os.programdir(), "core", "sandbox", "modules", "import"), + path.join(global.directory(), "modules")} for _, name in ipairs(addoninfo.globalmodules or {}) do local modulepath = (name:gsub("%.", "/")) .. ".lua" - for _, moduledir in ipairs({os.programdir(), global.directory()}) do - if os.isfile(path.join(moduledir, "modules", modulepath)) then + for _, moduledir in ipairs(moduledirs) do + if os.isfile(path.join(moduledir, modulepath)) then return string.format("global module(%s) conflicts, it has been provided by %s!\nplease rename it in the addon manifest.", - name, moduledir == os.programdir() and "xmake" or path.join(moduledir, "modules")) + name, moduledir:startswith(os.programdir()) and "xmake" or moduledir) end end end diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 2d2720fba..3d98a3743 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2117,11 +2117,17 @@ function _instance:fetch(opt) -- always install to the local project directory? -- @see https://github.com/xmake-io/xmake/pull/4376 + -- + -- @note the host packages are the tools which build the other packages, e.g. the toolchains, + -- they do not depend on the project configuration and they are shared between the projects, + -- so they are only installed locally with their own policy + -- @see https://github.com/xmake-io/xmake/issues/7716 + local policyname = self:is_host() and "package.host.install_locally" or "package.install_locally" local install_locally - if project and project.policy("package.install_locally") then + if project and project.policy(policyname) then install_locally = true end - if install_locally == nil and self:policy("package.install_locally") then + if install_locally == nil and self:policy(policyname) then install_locally = true end if not self:is_local() and install_locally and system ~= true then @@ -3110,12 +3116,20 @@ end -- -- @param opt the options, e.g. {localdir = true} -- - localdir: return the local project packages directory (build/.packages) --- instead of the global directory (~/.xmake/packages) +-- instead of the global directory (~/.xmake/packages), +-- it can be overridden with `XMAKE_PKG_LOCALDIR` -- -- @return the install directory path -- function package.installdir(opt) if opt and opt.localdir then + -- the parent process passes its local directory to the sub-process which builds + -- a package, so the packages it installs locally land in the same place and are + -- not installed twice, @see https://github.com/xmake-io/xmake/issues/7716 + local localdir = os.getenv("XMAKE_PKG_LOCALDIR") + if localdir then + return path.normalize(path.absolute(localdir)) + end return path.join(config.builddir({absolute = true}), ".packages") end local installdir = package._INSTALLDIR diff --git a/xmake/core/platform/menu.lua b/xmake/core/platform/menu.lua index cec901ee8..77a57381d 100644 --- a/xmake/core/platform/menu.lua +++ b/xmake/core/platform/menu.lua @@ -42,7 +42,7 @@ function _remote_build_is_connected() local projectdir = os.projectdir() local projectfile = os.projectfile() if projectfile and os.isfile(projectfile) and projectdir then - local workdir = path.join(config.directory(), "remote_build") + local workdir = path.join(config.directory(), "service", "remote_build") local statusfile = path.join(workdir, "status.txt") if os.isfile(statusfile) then local status = io.load(statusfile) diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 617a792d6..81a8b6924 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -158,6 +158,12 @@ function policy.policies() ["package.install_always"] = {description = "Always install packages every time.", type = "boolean"}, -- Install packages in the local project folder ["package.install_locally"] = {description = "Install packages in the local project folder.", default = false, type = "boolean"}, + -- Install the host packages in the local project folder + -- + -- the host packages are the tools which build the other packages, e.g. the toolchains, + -- they do not depend on the project configuration and they are shared between the projects, + -- so they have their own policy, @see https://github.com/xmake-io/xmake/issues/7716 + ["package.host.install_locally"] = {description = "Install the host packages in the local project folder.", default = false, type = "boolean"}, -- Keep package source code after installing (disable source dir cleanup) ["package.keep_source"] = {description = "Keep package source code after installing.", default = false, type = "boolean"}, -- Set custom headers when downloading package diff --git a/xmake/core/sandbox/modules/import/core/base/scheduler.lua b/xmake/core/sandbox/modules/import/core/base/scheduler.lua index 222bee391..a3f9741c3 100644 --- a/xmake/core/sandbox/modules/import/core/base/scheduler.lua +++ b/xmake/core/sandbox/modules/import/core/base/scheduler.lua @@ -96,7 +96,11 @@ end -- resume the given coroutine function sandbox_core_base_scheduler.co_resume(co, ...) - return scheduler:resume(co:thread(), ...) + local ok, errors = scheduler:co_resume(co, ...) + if not ok then + raise(errors) + end + return ok, errors end -- suspend the current coroutine |
