summaryrefslogtreecommitdiff
path: root/xmake/core
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/core')
-rw-r--r--xmake/core/base/poller.lua16
-rw-r--r--xmake/core/base/scheduler.lua14
-rw-r--r--xmake/core/base/task.lua36
-rw-r--r--xmake/core/package/addon.lua13
-rw-r--r--xmake/core/package/package.lua20
-rw-r--r--xmake/core/platform/menu.lua2
-rw-r--r--xmake/core/project/policy.lua6
-rw-r--r--xmake/core/sandbox/modules/import/core/base/scheduler.lua6
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