summaryrefslogtreecommitdiff
path: root/xmake/core
diff options
context:
space:
mode:
authorruki <[email protected]>2025-01-09 10:19:14 +0800
committerGitHub <[email protected]>2025-01-09 10:19:14 +0800
commit8e24b5a44dcffbee1444d715909a64014e11e866 (patch)
treea2f0aaf7b582dae30d4db636efd199ccb158e0d8 /xmake/core
parent1cf6a7f479837b471a5f91410359d86983828e6a (diff)
parent6317ffd0fe312360eb5f6e079320c01c95870ad0 (diff)
Merge pull request #6001 from xmake-io/namespace
Support for namespace
Diffstat (limited to 'xmake/core')
-rw-r--r--xmake/core/base/cli.lua4
-rw-r--r--xmake/core/base/interpreter.lua215
-rw-r--r--xmake/core/base/private/instance_deps.lua12
-rw-r--r--xmake/core/base/task.lua31
-rw-r--r--xmake/core/package/package.lua66
-rw-r--r--xmake/core/project/config.lua51
-rw-r--r--xmake/core/project/option.lua68
-rw-r--r--xmake/core/project/package.lua13
-rw-r--r--xmake/core/project/project.lua120
-rw-r--r--xmake/core/project/rule.lua24
-rw-r--r--xmake/core/project/target.lua111
-rw-r--r--xmake/core/sandbox/modules/get_config.lua17
-rw-r--r--xmake/core/sandbox/modules/has_config.lua23
-rw-r--r--xmake/core/sandbox/modules/has_package.lua15
-rw-r--r--xmake/core/sandbox/modules/import/core/base/process.lua4
-rw-r--r--xmake/core/sandbox/modules/import/core/project/project.lua9
-rw-r--r--xmake/core/sandbox/modules/is_config.lua17
-rw-r--r--xmake/core/sandbox/sandbox.lua36
-rw-r--r--xmake/core/tool/toolchain.lua18
19 files changed, 651 insertions, 203 deletions
diff --git a/xmake/core/base/cli.lua b/xmake/core/base/cli.lua
index a5d3db9ba..f9a73759f 100644
--- a/xmake/core/base/cli.lua
+++ b/xmake/core/base/cli.lua
@@ -90,6 +90,10 @@ function cli.parsev(argv, flags)
elseif value:startswith("--") then
-- "--key:value", "--key=value", "--long-flag"
local sep = value:find("[=:]", 3, false)
+ -- ignore namespace, e.g. `--namespace::opt=`
+ if sep and value:sub(sep, sep + 1) == "::" then
+ sep = value:find("=", 3, false)
+ end
if sep then
table.insert(parsed, cli._make_option(value:sub(3, sep - 1), value:sub(sep + 1), false, argv, index))
else
diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua
index 71250be6d..4e5aaf8c7 100644
--- a/xmake/core/base/interpreter.lua
+++ b/xmake/core/base/interpreter.lua
@@ -27,6 +27,7 @@ local path = require("base/path")
local table = require("base/table")
local utils = require("base/utils")
local string = require("base/string")
+local hashset = require("base/hashset")
local scopeinfo = require("base/scopeinfo")
local deprecated = require("base/deprecated")
local sandbox = require("sandbox/sandbox")
@@ -86,9 +87,7 @@ function interpreter._traceback(errors)
end
-- merge the current root values to the previous scope
-function interpreter._merge_root_scope(root, root_prev, override)
-
- -- merge it
+function interpreter:_merge_root_scope(root, root_prev, override)
root_prev = root_prev or {}
for scope_kind_and_name, _ in pairs(root or {}) do
-- only merge sub-scope for each kind("target@@xxxx") or __rootkind
@@ -111,16 +110,12 @@ function interpreter._merge_root_scope(root, root_prev, override)
root_prev[scope_kind_and_name] = scope_values
end
end
-
- -- ok?
return root_prev
end
-- fetch the root values to the child values in root scope
-- and we will only use the child values if be override mode
-function interpreter._fetch_root_scope(root)
-
- -- fetch it
+function interpreter:_fetch_root_scope(root)
for scope_kind_and_name, _ in pairs(root or {}) do
-- is scope_kind@@scope_name?
@@ -128,21 +123,55 @@ function interpreter._fetch_root_scope(root)
if #scope_kind_and_name == 2 then
local scope_kind = scope_kind_and_name[1]
local scope_name = scope_kind_and_name[2]
- local scope_values = root[scope_kind .. "@@" .. scope_name] or {}
- local scope_root = root[scope_kind] or {}
- for name, values in pairs(scope_root) do
- if not name:startswith("__override_") then
- if scope_root["__override_" .. name] then
- if scope_values[name] == nil then
- scope_values[name] = values
- scope_values["__override_" .. name] = true
+
+ -- we only fetch the root values to the target values, e.g. target@@ns1::ns2::bar"
+ -- and ignore root namespace values, e.g. target@@ns1::ns2::
+ if not scope_name:endswith("::") then
+ local scope_values = root[scope_kind .. "@@" .. scope_name] or {}
+ local namespaces = scope_name:split("::", {plain = true})
+ table.remove(namespaces)
+ table.insert(namespaces, 1, "")
+
+ -- add values in global root scope, all namespace root scopes
+ local namespace
+ local scope_rootkeys = {}
+ for idx, namespace_part in ipairs(namespaces) do
+ local scope_rootkey = scope_kind
+ if idx ~= 1 then
+ if not namespace then
+ namespace = namespace_part
+ else
+ namespace = namespace .. "::" .. namespace_part
+ end
+ scope_rootkey = scope_kind .. "@@" .. namespace .. "::"
+ end
+ table.insert(scope_rootkeys, scope_rootkey)
+ end
+ -- we need to add root values in head
+ --
+ -- e.g.
+ -- add root values to ns1::ns2::bar from target@@ns1::ns2::
+ -- add root values to ns1::ns2::bar from target@@ns1::
+ -- add root values to ns1::ns2::bar from target
+ --
+ for idx = #scope_rootkeys, 1, -1 do
+ local scope_rootkey = scope_rootkeys[idx]
+ local scope_root = root[scope_rootkey] or {}
+ for name, values in pairs(scope_root) do
+ if not name:startswith("__override_") then
+ if scope_root["__override_" .. name] then
+ if scope_values[name] == nil then
+ scope_values[name] = values
+ scope_values["__override_" .. name] = true
+ end
+ else
+ scope_values[name] = table.join(values, scope_values[name] or {})
+ end
end
- else
- scope_values[name] = table.join(values, scope_values[name] or {})
end
end
+ root[scope_kind .. "@@" .. scope_name] = scope_values
end
- root[scope_kind .. "@@" .. scope_name] = scope_values
end
end
end
@@ -166,27 +195,15 @@ end
-- register scope end: scopename_end()
function interpreter:_api_register_scope_end(...)
assert(self and self._PUBLIC and self._PRIVATE)
-
- -- done
for _, apiname in ipairs({...}) do
- -- check
- assert(apiname)
-
-- register scope api
self:api_register(nil, apiname .. "_end", function (self, ...)
-
- -- check
assert(self and self._PRIVATE and apiname)
- -- the scopes
- local scopes = self._PRIVATE._SCOPES
- assert(scopes)
-
-- enter root scope
+ local scopes = self._PRIVATE._SCOPES
scopes._CURRENT = nil
-
- -- clear scope kind
scopes._CURRENT_KIND = nil
end)
end
@@ -239,11 +256,16 @@ function interpreter:_api_register_xxx_values(scope_kind, action, apifunc, ...)
local implementation = function (self, scopes, apiname, ...)
-- init root scopes
+ local namespace = self._PRIVATE._NAMESPACE_STR
scopes._ROOT = scopes._ROOT or {}
-- init current root scope
- local root = scopes._ROOT[scope_kind] or {}
- scopes._ROOT[scope_kind] = root
+ local rootkey = scope_kind
+ if namespace then
+ rootkey = scope_kind .. "@@" .. namespace .. "::"
+ end
+ local root = scopes._ROOT[rootkey] or {}
+ scopes._ROOT[rootkey] = root
-- clear the current scope if be not belong to the current scope kind
if scopes._CURRENT and scopes._CURRENT_KIND ~= scope_kind then
@@ -522,18 +544,49 @@ function interpreter:_make(scope_kind, deduplicate, enable_filter)
local results = {}
local scope_opt = {interpreter = self, deduplicate = deduplicate, enable_filter = enable_filter}
if scope_kind and scope_kind:startswith("root.") then
-
- local root_scope = scopes._ROOT[scope_kind:sub(6)]
- if root_scope then
+ local root_scope = {}
+ local empty = true
+ local kind_prefix = scope_kind:sub(6)
+ for kind, scope in pairs(scopes._ROOT) do
+ if kind:startswith(kind_prefix) then
+ local namespace = kind:match(kind_prefix .. "@@(.+)::")
+ if namespace or kind == kind_prefix then
+ for k, v in pairs(scope) do
+ if namespace then
+ root_scope[namespace .. "::" .. k] = v
+ else
+ root_scope[k] = v
+ end
+ end
+ end
+ empty = false
+ end
+ end
+ if root_scope and not empty then
results = self:_handle(root_scope, deduplicate, enable_filter)
end
return scopeinfo.new(scope_kind, results, scope_opt)
-- get the root scope info without scope kind
elseif scope_kind == "root" or scope_kind == nil then
-
- local root_scope = scopes._ROOT["__rootkind"]
- if root_scope then
+ local root_scope = {}
+ local empty = true
+ for kind, scope in pairs(scopes._ROOT) do
+ if kind:startswith("__rootkind") then
+ local namespace = kind:match("__rootkind@@(.+)::")
+ if namespace or kind == "__rootkind" then
+ for k, v in pairs(scope) do
+ if namespace then
+ root_scope[namespace .. "::" .. k] = v
+ else
+ root_scope[k] = v
+ end
+ end
+ end
+ empty = false
+ end
+ end
+ if root_scope and not empty then
results = self:_handle(root_scope, deduplicate, enable_filter)
end
return scopeinfo.new(scope_kind, results, scope_opt)
@@ -546,7 +599,7 @@ function interpreter:_make(scope_kind, deduplicate, enable_filter)
if scope_for_kind then
-- fetch the root values in root scope first
- interpreter._fetch_root_scope(scopes._ROOT)
+ self:_fetch_root_scope(scopes._ROOT)
-- merge results
for scope_name, scope in pairs(scope_for_kind) do
@@ -594,7 +647,7 @@ function interpreter:_script(script)
end
-- make sandbox instance with the given script
- local instance, errors = sandbox.new(script, self:filter(), self:scriptdir())
+ local instance, errors = sandbox.new(script, {filter = self:filter(), rootdir = self:scriptdir(), namespace = self:namespace()})
if not instance then
return nil, errors
end
@@ -680,6 +733,8 @@ function interpreter.new()
instance:api_register(nil, "add_subdirs", interpreter.api_builtin_add_subdirs)
instance:api_register(nil, "add_subfiles", interpreter.api_builtin_add_subfiles)
instance:api_register(nil, "set_xmakever", interpreter.api_builtin_set_xmakever)
+ instance:api_register(nil, "namespace", interpreter.api_builtin_namespace)
+ instance:api_register(nil, "namespace_end",interpreter.api_builtin_namespace_end)
-- register the interpreter interfaces
instance:api_register(nil, "interp_save_scope", interpreter.api_interp_save_scope)
@@ -765,6 +820,17 @@ function interpreter:mtimes()
return self._PRIVATE._MTIMES
end
+-- get current namespace
+function interpreter:namespace()
+ return self._PRIVATE._NAMESPACE_STR
+end
+
+-- get namespaces
+function interpreter:namespaces()
+ local namespaces = self._PRIVATE._NAMESPACES
+ return namespaces and namespaces:to_array()
+end
+
-- get filter
function interpreter:filter()
assert(self and self._PRIVATE)
@@ -924,7 +990,7 @@ end
-- {
-- scope_kind1
-- {
--- "scope_name1"
+-- "namespace1::scope_name1"
-- {
--
-- }
@@ -932,7 +998,7 @@ end
--
-- scope_kind2
-- {
--- "scope_name1"
+-- "namespace1::namespace2::scope_name1"
-- {
--
-- }
@@ -952,6 +1018,10 @@ function interpreter:api_register_scope(...)
local scope_args = table.pack(...)
local scope_name = scope_args[1]
local scope_info = scope_args[2]
+ local namespace = self._PRIVATE._NAMESPACE_STR
+ if scope_name ~= nil and namespace then
+ scope_name = namespace .. "::" .. scope_name
+ end
-- check invalid scope name, @see https://github.com/xmake-io/xmake/issues/4547
if scope_args.n > 0 and type(scope_name) ~= "string" then
@@ -992,6 +1062,8 @@ function interpreter:api_register_scope(...)
scopes._ROOT = scopes._ROOT or {}
if scope_name ~= nil then
scopes._ROOT[scope_kind .. "@@" .. scope_name] = {}
+ elseif namespace then
+ scopes._ROOT[scope_kind .. "@@" .. namespace .. "::"] = {}
end
-- with scope info? translate it
@@ -1058,13 +1130,17 @@ end
-- {
-- scope_kind
-- {
+-- name1 = {"value3"}
+-- }
+-- scope_kind@@namespace::
+-- {
-- name2 = {"value3"}
-- }
-- }
--
-- scope_kind
-- {
--- "scope_name" <-- _SCOPES._CURRENT
+-- "namespace::scope_name" <-- _SCOPES._CURRENT
-- {
-- name1 = {"value1"}
-- name2 = {"value1", "value2", ...}
@@ -1811,12 +1887,12 @@ function interpreter:api_builtin_includes(...)
scopes._CURRENT = scope_prev
-- fetch the root values in root scopes first
- interpreter._fetch_root_scope(scopes._ROOT)
+ self:_fetch_root_scope(scopes._ROOT)
-- restore the previous root scope and merge current root scope
-- it will override the previous values if the current values are override mode
-- so we priority use the values in subdirs scope
- scopes._ROOT = interpreter._merge_root_scope(scopes._ROOT, root_prev, true)
+ scopes._ROOT = self:_merge_root_scope(scopes._ROOT, root_prev, true)
-- get mtime of the file
self._PRIVATE._MTIMES[path.relative(file, self._PRIVATE._ROOTDIR)] = os.mtime(file)
@@ -1844,6 +1920,51 @@ function interpreter:api_builtin_add_subfiles(...)
deprecated.add("includes(%s)", "add_subfiles(%s)", table.concat(files, ", "), table.concat(files, ", "))
end
+-- the builtin api: namespace()
+function interpreter:api_builtin_namespace(name, callback)
+
+ -- enter root scope
+ self:api_interp_save_scope()
+ local scopes = self._PRIVATE._SCOPES
+ scopes._CURRENT = nil
+ scopes._CURRENT_KIND = nil
+
+ -- enter namespace
+ local namespace = self._PRIVATE._NAMESPACE
+ if namespace == nil then
+ namespace = {}
+ self._PRIVATE._NAMESPACE = namespace
+ end
+ table.insert(namespace, name)
+ self._PRIVATE._NAMESPACE_STR = table.concat(namespace, "::")
+ -- save namespaces
+ local namespaces = self._PRIVATE._NAMESPACES
+ if namespaces == nil then
+ namespaces = hashset.new()
+ self._PRIVATE._NAMESPACES = namespaces
+ end
+ namespaces:insert(self._PRIVATE._NAMESPACE_STR)
+ if callback and type(callback) == "function" then
+ callback()
+ self:api_builtin_namespace_end()
+ end
+end
+
+-- the builtin api: namespace_end()
+function interpreter:api_builtin_namespace_end()
+ assert(self and self._PRIVATE)
+ local namespace = self._PRIVATE._NAMESPACE
+ if namespace then
+ table.remove(namespace)
+ end
+ if namespace and #namespace > 0 then
+ self._PRIVATE._NAMESPACE_STR = table.concat(namespace, "::")
+ else
+ self._PRIVATE._NAMESPACE_STR = nil
+ end
+ self:api_interp_restore_scope()
+end
+
-- the interpreter api: interp_save_scope()
-- save the current scope
function interpreter:api_interp_save_scope()
diff --git a/xmake/core/base/private/instance_deps.lua b/xmake/core/base/private/instance_deps.lua
index 17145ac6f..2c9c1a7e2 100644
--- a/xmake/core/base/private/instance_deps.lua
+++ b/xmake/core/base/private/instance_deps.lua
@@ -46,6 +46,12 @@ function instance_deps.load_deps(instance, instances, deps, orderdeps, depspath,
-- @see https://github.com/xmake-io/xmake/issues/3144
local depname = plaindeps[total + 1 - idx]
local depinst = instances[depname]
+ if depinst == nil and instance.namespace then
+ local namespace = instance:namespace()
+ if namespace then
+ depinst = instances[namespace .. "::" .. depname]
+ end
+ end
if depinst then
local continue_walk = true
if walkdep then
@@ -79,6 +85,12 @@ function instance_deps._sort_instance(instance, instances, orderinstances, insta
instancerefs[instance:name()] = true
for _, depname in ipairs(table.wrap(instance:get("deps"))) do
local depinst = instances[depname]
+ if depinst == nil and instance.namespace then
+ local namespace = instance:namespace()
+ if namespace then
+ depinst = instances[namespace .. "::" .. depname]
+ end
+ end
if depinst then
local depspath_sub
if depspath then
diff --git a/xmake/core/base/task.lua b/xmake/core/base/task.lua
index deea228aa..a3fde1913 100644
--- a/xmake/core/base/task.lua
+++ b/xmake/core/base/task.lua
@@ -221,17 +221,12 @@ end
-- bind script with a sandbox instance
function task._bind_script(interp, script)
-
- -- make sandbox instance with the given script
- local instance, errors = sandbox.new(script, interp:filter(), interp:rootdir())
+ local instance, errors = sandbox.new(script, {
+ filter = interp:filter(), rootdir = interp:rootdir(), namespace = interp:namespace()})
if not instance then
return nil, errors
end
-
- -- check
assert(instance:script())
-
- -- update option script
return instance:script()
end
@@ -373,7 +368,12 @@ end
-- new a task instance
function task.new(name, info)
local instance = table.inherit(task)
- instance._NAME = name
+ local parts = name:split("::", {plain = true})
+ instance._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ instance._NAMESPACE = table.concat(parts, "::")
+ end
instance._INFO = info
return instance
end
@@ -475,13 +475,24 @@ function task:name()
return self._NAME
end
+-- get the namespace
+function task:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name
+function task:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
+end
+
-- run given task
function task:run(...)
-- check
local on_run = self:get("run")
if not on_run then
- return false, string.format("task(\"%s\"): no run script, please call on_run() first!", self:name())
+ return false, string.format("task(\"%s\"): no run script, please call on_run() first!", self:fullname())
end
-- save the current directory
@@ -492,8 +503,6 @@ function task:run(...)
-- restore the current directory
os.cd(curdir)
-
- -- ok?
return ok, errors
end
diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua
index 068e95ab6..741ca318c 100644
--- a/xmake/core/package/package.lua
+++ b/xmake/core/package/package.lua
@@ -55,8 +55,25 @@ local sandbox_module = require("sandbox/modules/import/core/sandbox/module")
-- new an instance
function _instance.new(name, info, opt)
opt = opt or {}
+ local parts = name:split("::", {plain = true})
local instance = table.inherit(_instance)
- instance._NAME = name
+ local managers = package._memcache():get("managers")
+ if managers == nil and #parts == 2 then
+ managers = hashset.new()
+ for _, dir in ipairs(os.dirs(path.join(os.programdir(), "modules/package/manager/*"))) do
+ managers:insert(path.filename(dir))
+ end
+ package._memcache():set("managers", managers)
+ end
+ if #parts == 2 and managers and managers:has(parts[1]) then
+ instance._NAME = name
+ else
+ instance._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ instance._NAMESPACE = table.concat(parts, "::")
+ end
+ end
instance._INFO = info
instance._REPO = opt.repo
instance._SCRIPTDIR = opt.scriptdir and path.absolute(opt.scriptdir)
@@ -73,11 +90,32 @@ function _instance:_memcache()
return cache
end
--- get the package name
+-- get the package name without namespace
function _instance:name()
return self._NAME
end
+-- get the namespace
+function _instance:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name (with namespace)
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
+end
+
+-- get the display name (with namespace and ~label)
+function _instance:displayname()
+ return self._DISPLAYNAME
+end
+
+-- set the display name
+function _instance:displayname_set(displayname)
+ self._DISPLAYNAME = displayname
+end
+
-- get the type: package
function _instance:type()
return "package"
@@ -1276,6 +1314,7 @@ function _instance:toolchains()
local toolchain_opt = project and project.extraconf("target.toolchains", name) or {}
toolchain_opt.plat = self:plat()
toolchain_opt.arch = self:arch()
+ toolchain_opt.namespace = self:namespace()
local toolchain_inst, errors = toolchain.load(name, toolchain_opt)
if not toolchain_inst and project then
toolchain_inst = project.toolchain(name, toolchain_opt)
@@ -1518,16 +1557,6 @@ function _instance:label()
return requireinfo and requireinfo.label
end
--- get the display name
-function _instance:displayname()
- return self._DISPLAYNAME
-end
-
--- set the display name
-function _instance:displayname_set(displayname)
- self._DISPLAYNAME = displayname
-end
-
-- invalidate configs
function _instance:_invalidate_configs()
self._CONFIGS = nil
@@ -2916,7 +2945,7 @@ function package.load_from_system(packagename)
end
-- make sandbox instance with the given script
- instance, errors = sandbox.new(on_install, interp:filter())
+ instance, errors = sandbox.new(on_install, {filter = interp:filter(), namespace = interp:namespace()})
if not instance then
return nil, errors
end
@@ -2972,7 +3001,16 @@ function package.load_from_project(packagename, project)
-- get package info
local packageinfo = packages[packagename]
- if not packageinfo then
+ if packageinfo == nil and project.namespaces() then
+ for _, namespace in ipairs(project.namespaces()) do
+ packageinfo = packages[namespace .. "::" .. packagename]
+ if packageinfo then
+ packagename = namespace .. "::" .. packagename
+ break
+ end
+ end
+ end
+ if packageinfo == nil then
return
end
diff --git a/xmake/core/project/config.lua b/xmake/core/project/config.lua
index 650bbc4a6..35ccd9145 100644
--- a/xmake/core/project/config.lua
+++ b/xmake/core/project/config.lua
@@ -52,6 +52,23 @@ function config._use_workingdir()
return use_workingdir
end
+-- the current config is belong to the given config values?
+function config._is_value(value, ...)
+ if value == nil then
+ return false
+ end
+
+ value = tostring(value)
+ for _, v in ipairs(table.pack(...)) do
+ -- escape '-'
+ v = tostring(v)
+ if value == v or value:find("^" .. v:gsub("%-", "%%-") .. "$") then
+ return true
+ end
+ end
+ return false
+end
+
-- get the current given configuration
function config.get(name)
local value = nil
@@ -260,17 +277,17 @@ end
-- the current mode is belong to the given modes?
function config.is_mode(...)
- return config.is_value("mode", ...)
+ return config._is_value(config.get("mode"), ...)
end
-- the current platform is belong to the given platforms?
function config.is_plat(...)
- return config.is_value("plat", ...)
+ return config._is_value(config.get("plat"), ...)
end
-- the current architecture is belong to the given architectures?
function config.is_arch(...)
- return config.is_value("arch", ...)
+ return config._is_value(config.get("arch"), ...)
end
-- is cross-compilation?
@@ -278,34 +295,6 @@ function config.is_cross()
return is_cross(config.plat(), config.arch())
end
--- the current config is belong to the given config values?
-function config.is_value(name, ...)
- local value = config.get(name)
- if value == nil then
- return false
- end
-
- value = tostring(value)
- for _, v in ipairs(table.pack(...)) do
- -- escape '-'
- v = tostring(v)
- if value == v or value:find("^" .. v:gsub("%-", "%%-") .. "$") then
- return true
- end
- end
- return false
-end
-
--- has the given configs?
-function config.has(...)
- for _, name in ipairs(table.pack(...)) do
- if name and type(name) == "string" and config.get(name) then
- return true
- end
- end
- return false
-end
-
-- dump the configure
function config.dump()
if not option.get("quiet") then
diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua
index 0e4499f57..18b9dc363 100644
--- a/xmake/core/project/option.lua
+++ b/xmake/core/project/option.lua
@@ -44,9 +44,14 @@ local sandbox_module = require("sandbox/modules/import/core/sandbox/module")
-- new an instance
function _instance.new(name, info)
- local instance = table.inherit(_instance)
- instance._NAME = name
- instance._INFO = info
+ local instance = table.inherit(_instance)
+ local parts = name:split("::", {plain = true})
+ instance._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ instance._NAMESPACE = table.concat(parts, "::")
+ end
+ instance._INFO = info
instance._CACHEID = 1
return instance
end
@@ -63,7 +68,7 @@ function _instance:_save()
self:set("check_before", nil)
-- save option
- option._cache():set(self:name(), self:info())
+ option._cache():set(self:fullname(), self:info())
-- restore scripts
self:set("check", check)
@@ -73,7 +78,7 @@ end
-- clear the option info for cache
function _instance:_clear()
- option._cache():set(self:name(), nil)
+ option._cache():set(self:fullname(), nil)
end
-- check snippets
@@ -129,7 +134,7 @@ function _instance:_do_check_cxsnippets(snippets)
end
end
if #table.keys(snippets_output) > 1 then
- return false, -1, string.format("option(%s): only support for only one snippet with output!", self:name())
+ return false, -1, string.format("option(%s): only support for only one snippet with output!", self:fullname())
end
end
@@ -309,6 +314,10 @@ function _instance:_check()
if name:startswith("__") then
name = name:sub(3)
end
+ local namespace = self:namespace()
+ if namespace then
+ name = namespace .. "::" .. name
+ end
-- trace
local result
@@ -336,7 +345,7 @@ end
function _instance:check()
-- the option name
- local name = self:name()
+ local name = self:fullname()
-- get default value, TODO: enable will be deprecated
local default = self:get("default")
@@ -378,24 +387,24 @@ end
-- get the option value
function _instance:value()
- return config.get(self:name())
+ return config.get(self:fullname())
end
-- set the option value
function _instance:set_value(value)
- config.set(self:name(), value)
+ config.set(self:fullname(), value)
self:_save()
end
-- clear the option status and need recheck it
function _instance:clear()
- config.set(self:name(), nil)
+ config.set(self:fullname(), nil)
self:_clear()
end
-- this option is enabled?
function _instance:enabled()
- return config.get(self:name())
+ return config.get(self:fullname())
end
-- enable or disable this option
@@ -409,8 +418,8 @@ function _instance:enable(enabled, opt)
opt = opt or {}
-- enable or disable this option?
- if not config.readonly(self:name()) or opt.force then
- config.set(self:name(), enabled, opt)
+ if not config.readonly(self:fullname()) or opt.force then
+ config.set(self:fullname(), enabled, opt)
end
-- save or clear this option in cache
@@ -474,7 +483,14 @@ end
function _instance:dep(name)
local deps = self:deps()
if deps then
- return deps[name]
+ local dep = deps[name]
+ if dep == nil then
+ local namespace = self:namespace()
+ if namespace then
+ dep = deps[namespace .. "::" .. name]
+ end
+ end
+ return dep
end
end
@@ -493,9 +509,20 @@ function _instance:name()
return self._NAME
end
+-- get the namespace
+function _instance:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
+end
+
-- get the option description
function _instance:description()
- return self:get("description") or ("The " .. self:name() .. " option")
+ return self:get("description") or ("The " .. self:fullname() .. " option")
end
-- get the cache key
@@ -645,13 +672,12 @@ function option.new(name, info)
end
-- load the option info from the cache
-function option.load(name)
-
- -- check
- assert(name)
-
- -- get info
+function option.load(name, opt)
+ opt = opt or {}
local info = option._cache():get(name)
+ if info == nil and opt.namespace then
+ info = option._cache():get(opt.namespace .. "::" .. name)
+ end
if info == nil then
return
end
diff --git a/xmake/core/project/package.lua b/xmake/core/project/package.lua
index 70f89a1f8..67000bdc6 100644
--- a/xmake/core/project/package.lua
+++ b/xmake/core/project/package.lua
@@ -69,6 +69,12 @@ function _instance:name()
return self._NAME
end
+-- get the full name
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
+end
+
-- get the package version
function _instance:version()
@@ -107,6 +113,11 @@ function _instance:requirestr()
return self:get("__requirestr")
end
+-- get the namespace
+function _instance:namespace()
+ return self:get("__namespace")
+end
+
-- get the require configuration from the given name
--
-- e.g.
@@ -369,7 +380,7 @@ end
-- we need to sort package set keys by this string
-- @see https://github.com/xmake-io/xmake/pull/2971#issuecomment-1290052169
function _instance:__tostring()
- return "<package: " .. self:name() .. ">"
+ return "<package: " .. self:fullname() .. ">"
end
-- get cache
diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua
index 77793d3e5..43271c7b0 100644
--- a/xmake/core/project/project.lua
+++ b/xmake/core/project/project.lua
@@ -108,12 +108,28 @@ end
-- the current config is belong to the given config values?
function project._api_is_config(interp, name, ...)
- return config.is_value(name, ...)
+ local value = config.get(name)
+ local namespace = interp:namespace()
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ return config._is_value(value, ...)
end
-- some configs are enabled?
function project._api_has_config(interp, ...)
- return config.has(...)
+ local names = table.pack(...)
+ local namespace = interp:namespace()
+ for _, name in ipairs(names) do
+ local value = config.get(name)
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ if value then
+ return true
+ end
+ end
+ return false
end
-- some packages are enabled?
@@ -121,8 +137,19 @@ function project._api_has_package(interp, ...)
-- only for loading targets
local requires = project._memcache():get("requires")
if requires then
- for _, name in ipairs(table.pack(...)) do
- local pkg = requires[name]
+ for _, packagename in ipairs(table.pack(...)) do
+ local pkg = requires[packagename]
+ -- attempt to get package with namespace
+ if pkg == nil and packagename:find("::", 1, true) then
+ local parts = packagename:split("::", {plain = true})
+ local namespace_pkg = requires[parts[#parts]]
+ if namespace_pkg and namespace_pkg:namespace() then
+ local fullname = namespace_pkg:fullname()
+ if fullname:endswith(packagename) then
+ pkg = namespace_pkg
+ end
+ end
+ end
if pkg and pkg:enabled() then
return true
end
@@ -132,7 +159,12 @@ end
-- get config from the given name
function project._api_get_config(interp, name)
- return config.get(name)
+ local value = config.get(name)
+ local namespace = interp:namespace()
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ return value
end
-- add module directories
@@ -383,7 +415,7 @@ function project._load_targets()
end
rulenames = table.unique(rulenames)
for _, rulename in ipairs(rulenames) do
- local r = project.rule(rulename) or rule.rule(rulename)
+ local r = project.rule(rulename, {namespace = t:namespace()}) or rule.rule(rulename)
if r then
-- only add target rules
if r:kind() == "target" then
@@ -524,7 +556,7 @@ function project._load_requires()
end
-- add require info
- requires[alias or packagename] = instance
+ requires[name] = instance
end
return requires
end
@@ -785,6 +817,10 @@ function project.filelock()
end
-- get the root configuration
+--
+-- get root values in project, e.g project.get("name")
+-- get root values in target, e.g. project.get("target.name")
+-- get root values in specific namespace, e.g. project.get("ns1::ns2::name"), project.get("target.ns1::ns2::name")
function project.get(name)
local rootinfo
if name and name:startswith("target.") then
@@ -824,6 +860,11 @@ function project.version()
return project.get("target.version")
end
+-- get the project namespaces
+function project.namespaces()
+ return project.interpreter():namespaces()
+end
+
-- init default policies
-- @see https://github.com/xmake-io/xmake/issues/5527
function project._init_default_policies()
@@ -911,9 +952,16 @@ function project.is_loaded()
end
-- get the given target
-function project.target(name)
+function project.target(name, opt)
+ opt = opt or {}
local targets = project.targets()
- return targets and targets[name]
+ if targets then
+ local t = targets[name]
+ if not t and opt.namespace then
+ t = targets[opt.namespace .. "::" .. name]
+ end
+ return t
+ end
end
-- add the given target, @note if the target name is the same, it will be replaced
@@ -963,8 +1011,16 @@ function project.ordertargets()
end
-- get the given option
-function project.option(name)
- return project.options()[name]
+function project.option(name, opt)
+ opt = opt or {}
+ local options = project.options()
+ if options then
+ local o = options[name]
+ if not o and opt.namespace then
+ o = options[opt.namespace .. "::" .. name]
+ end
+ return o
+ end
end
-- get options
@@ -1014,11 +1070,38 @@ function project.requires_str()
-- get raw requires
requires_str, requires_extra = project.get("requires"), project.get("__extra_requires")
+ local namespaces = project.namespaces()
+ if namespaces then
+ for _, namespace in ipairs(namespaces) do
+ local ns_requires_str, ns_requires_extra = project.get(namespace .. "::requires"), project.get(namespace .. "::__extra_requires")
+ if ns_requires_str then
+ requires_str = table.wrap(requires_str)
+ table.insert(requires_str, ns_requires_str)
+ end
+ if ns_requires_extra then
+ requires_extra = table.wrap(requires_extra)
+ table.join2(requires_extra, ns_requires_extra)
+ end
+ end
+ end
project._memcache():set("requires_str", requires_str or false)
project._memcache():set("requires_extra", requires_extra)
-- get raw requireconfs
local requireconfs_str, requireconfs_extra = project.get("requireconfs"), project.get("__extra_requireconfs")
+ if namespaces then
+ for _, namespace in ipairs(project.namespaces()) do
+ local ns_requireconfs_str, ns_requireconfs_extra = project.get(namespace .. "::requireconfs"), project.get(namespace .. "::__extra_requireconfs")
+ if ns_requireconfs_str then
+ requireconfs_str = table.wrap(requireconfs_str)
+ table.insert(requireconfs_str, ns_requireconfs_str)
+ end
+ if ns_requireconfs_extra then
+ requireconfs_extra = table.wrap(requireconfs_extra)
+ table.join2(requireconfs_extra, ns_requireconfs_extra)
+ end
+ end
+ end
project._memcache():set("requireconfs_str", requireconfs_str or false)
project._memcache():set("requireconfs_extra", requireconfs_extra)
end
@@ -1080,8 +1163,13 @@ function project.requireslock_version()
end
-- get the given rule
-function project.rule(name)
- return project.rules()[name]
+function project.rule(name, opt)
+ opt = opt or {}
+ local r = project.rules()[name]
+ if r == nil and opt.namespace then
+ r = project.rules()[opt.namespace .. "::" .. name]
+ end
+ return r
end
-- get project rules
@@ -1100,8 +1188,12 @@ end
-- get the given toolchain
function project.toolchain(name, opt)
+ opt = opt or {}
local toolchain_name = toolchain.parsename(name) -- we need to ignore `@packagename`
local info = project._toolchains()[toolchain_name]
+ if info == nil and opt.namespace then
+ info = project._toolchains()[opt.namespace .. "::" .. toolchain_name]
+ end
if info then
return toolchain.load_withinfo(name, info, opt)
end
@@ -1184,7 +1276,7 @@ function project.menu()
options_by_category[category] = options_by_category[category] or {}
-- append option to the current category
- options_by_category[category][opt:name()] = opt
+ options_by_category[category][opt:fullname()] = opt
end
-- make menu by category
diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua
index 75da4da39..5d44f7c25 100644
--- a/xmake/core/project/rule.lua
+++ b/xmake/core/project/rule.lua
@@ -60,12 +60,12 @@ function _instance:_build_deps()
end
self._DEPS = self._DEPS or {}
self._ORDERDEPS = self._ORDERDEPS or {}
- instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:name()})
+ instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:fullname()})
end
-- clone rule
function _instance:clone()
- local instance = rule.new(self:name(), self._INFO:clone())
+ local instance = rule.new(self:fullname(), self._INFO:clone())
instance._DEPS = self._DEPS
instance._ORDERDEPS = self._ORDERDEPS
instance._PACKAGE = self._PACKAGE
@@ -106,7 +106,23 @@ end
-- set the rule name
function _instance:name_set(name)
- self._NAME = name
+ local parts = name:split("::", {plain = true})
+ self._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ self._NAMESPACE = table.concat(parts, "::")
+ end
+end
+
+-- get the namespace
+function _instance:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
end
-- get the rule kind
@@ -331,7 +347,7 @@ end
function rule.new(name, info, opt)
opt = opt or {}
local instance = table.inherit(_instance)
- instance._NAME = name
+ instance:name_set(name)
instance._INFO = info
instance._PACKAGE = opt.package
if opt.package then
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index 1d3547660..a8796076c 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -55,9 +55,9 @@ local sandbox_module = require("sandbox/modules/import/core/sandbox/module")
-- new a target instance
function _instance.new(name, info)
local instance = table.inherit(_instance)
- instance._NAME = name
instance._INFO = info
instance._CACHEID = 1
+ instance:name_set(name)
return instance
end
@@ -75,7 +75,7 @@ end
function _instance:_load_rule(ruleinst, suffix)
-- init cache
- local key = ruleinst:name() .. (suffix and ("_" .. suffix) or "")
+ local key = ruleinst:fullname() .. (suffix and ("_" .. suffix) or "")
local cache = self._RULES_LOADED or {}
-- do load
@@ -90,7 +90,7 @@ function _instance:_load_rule(ruleinst, suffix)
-- before_load has been deprecated
if on_load and suffix == "before" then
- deprecated.add(ruleinst:name() .. ".on_load", ruleinst:name() .. ".before_load")
+ deprecated.add(ruleinst:fullname() .. ".on_load", ruleinst:fullname() .. ".before_load")
end
end
@@ -208,7 +208,7 @@ function _instance:_update_filerules()
end
rulenames = table.unique(rulenames)
for _, rulename in ipairs(rulenames) do
- local r = target._project() and target._project().rule(rulename) or rule.rule(rulename)
+ local r = target._project() and target._project().rule(rulename, {namespace = self:namespace()}) or rule.rule(rulename)
if r then
-- only add target rules
if r:kind() == "target" then
@@ -253,10 +253,13 @@ function _instance:_build_deps()
self._DEPS = self._DEPS or {}
self._ORDERDEPS = self._ORDERDEPS or {}
self._INHERITDEPS = self._INHERITDEPS or {}
- instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:name()})
+ instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:fullname()})
-- @see https://github.com/xmake-io/xmake/issues/4689
- instance_deps.load_deps(self, instances, {}, self._INHERITDEPS, {self:name()}, function (t, dep)
+ instance_deps.load_deps(self, instances, {}, self._INHERITDEPS, {self:fullname()}, function (t, dep)
local depinherit = t:extraconf("deps", dep:name(), "inherit")
+ if depinherit == nil then
+ depinherit = t:extraconf("deps", dep:fullname(), "inherit")
+ end
return depinherit == nil or depinherit
end)
end
@@ -518,9 +521,9 @@ end
-- clone target, @note we can just call it in after_load()
function _instance:clone()
if not self:_is_loaded() then
- os.raise("please call target:clone() in after_load().", self:name())
+ os.raise("please call target:clone() in after_load().", self:fullname())
end
- local instance = target.new(self:name(), self._INFO:clone())
+ local instance = target.new(self:fullname(), self._INFO:clone())
if self._DEPS then
instance._DEPS = table.clone(self._DEPS)
end
@@ -886,7 +889,23 @@ end
-- set the target name
function _instance:name_set(name)
- self._NAME = name
+ local parts = name:split("::", {plain = true})
+ self._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ self._NAMESPACE = table.concat(parts, "::")
+ end
+end
+
+-- get the namespace
+function _instance:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
end
-- get the target kind
@@ -1091,7 +1110,14 @@ end
function _instance:dep(name)
local deps = self:deps()
if deps then
- return deps[name]
+ local dep = deps[name]
+ if dep == nil then
+ local namespace = self:namespace()
+ if namespace then
+ dep = deps[namespace .. "::" .. name]
+ end
+ end
+ return dep
end
end
@@ -1137,7 +1163,11 @@ end
-- get target rule from the given rule name
function _instance:rule(name)
if self._RULES then
- return self._RULES[name]
+ local r = self._RULES[name]
+ if r == nil and self:namespace() then
+ r = self._RULES[self:namespace() .. "::" .. name]
+ end
+ return r
end
end
@@ -1147,7 +1177,7 @@ end
-- it will be replaced in the target:rules() and target:orderules(), but will be not replaced globally in the project.rules()
function _instance:rule_add(r)
self._RULES = self._RULES or {}
- self._RULES[r:name()] = r
+ self._RULES[r:fullname()] = r
self._ORDERULES = nil
end
@@ -1252,7 +1282,13 @@ function _instance:orderopts(opt)
orderopts = {}
for _, name in ipairs(table.wrap(self:get("options", opt))) do
local opt_ = nil
- if config.get(name) then opt_ = option.load(name) end
+ local enabled = config.get(name)
+ if enabled == nil and self:namespace() then
+ enabled = config.get(self:namespace() .. "::" .. name)
+ end
+ if enabled then
+ opt_ = option.load(name, {namespace = self:namespace()})
+ end
if opt_ then
table.insert(orderopts, opt_)
end
@@ -1303,6 +1339,17 @@ function _instance:orderpkgs(opt)
if requires then
for _, packagename in ipairs(table.wrap(self:get("packages", opt))) do
local pkg = requires[packagename]
+ -- attempt to get package with namespace
+ if pkg == nil and packagename:find("::", 1, true) then
+ local parts = packagename:split("::", {plain = true})
+ local namespace_pkg = requires[parts[#parts]]
+ if namespace_pkg and namespace_pkg:namespace() then
+ local fullname = namespace_pkg:fullname()
+ if fullname:endswith(packagename) then
+ pkg = namespace_pkg
+ end
+ end
+ end
if pkg and pkg:enabled() then
table.insert(packages, pkg)
end
@@ -1371,7 +1418,12 @@ function _instance:objectdir(opt)
if not objectdir then
objectdir = path.join(config.buildir(), ".objs")
end
- objectdir = path.join(objectdir, self:name())
+ local namespace = self:namespace()
+ if namespace then
+ objectdir = path.join(objectdir, (namespace:replace("::", path.sep())), self:name())
+ else
+ objectdir = path.join(objectdir, self:name())
+ end
-- get root directory of target
local intermediate_directory = self:policy("build.intermediate_directory")
@@ -1403,7 +1455,12 @@ function _instance:dependir(opt)
if not dependir then
dependir = path.join(config.buildir(), ".deps")
end
- dependir = path.join(dependir, self:name())
+ local namespace = self:namespace()
+ if namespace then
+ dependir = path.join(dependir, (namespace:replace("::", path.sep())), self:name())
+ else
+ dependir = path.join(dependir, self:name())
+ end
-- get root directory of target
local intermediate_directory = self:policy("build.intermediate_directory")
@@ -1435,7 +1492,12 @@ function _instance:autogendir(opt)
if not autogendir then
autogendir = path.join(config.buildir(), ".gens")
end
- autogendir = path.join(autogendir, self:name())
+ local namespace = self:namespace()
+ if namespace then
+ autogendir = path.join(autogendir, (namespace:replace("::", path.sep())), self:name())
+ else
+ autogendir = path.join(autogendir, self:name())
+ end
-- get root directory of target
local intermediate_directory = self:policy("build.intermediate_directory")
@@ -1533,6 +1595,10 @@ function _instance:targetdir()
if mode then
targetdir = path.join(targetdir, mode)
end
+ local namespace = self:namespace()
+ if namespace then
+ targetdir = path.join(targetdir, (namespace:replace("::", path.sep())))
+ end
end
return targetdir
end
@@ -1699,7 +1765,8 @@ function _instance:filerules(sourcefile)
if filerules then
override = filerules.override
for _, rulename in ipairs(table.wrap(filerules)) do
- local r = target._project().rule(rulename) or rule.rule(rulename) or self:rule(rulename)
+ local r = target._project().rule(rulename, {namespace = self:namespace()}) or
+ rule.rule(rulename) or self:rule(rulename)
if r then
table.insert(rules, r)
end
@@ -1916,7 +1983,8 @@ function _instance:sourcefiles()
end
if #results == 0 then
local sourceinfo = self:sourceinfo("files", file) or {}
- utils.warning("%s:%d${clear}: cannot match %s_files(\"%s\") in %s(%s)", sourceinfo.file or "", sourceinfo.line or -1, (removed and "remove" or "add"), file, self:type(), self:name())
+ utils.warning("%s:%d${clear}: cannot match %s_files(\"%s\") in %s(%s)",
+ sourceinfo.file or "", sourceinfo.line or -1, (removed and "remove" or "add"), file, self:type(), self:fullname())
end
-- process source files
@@ -2438,6 +2506,7 @@ function _instance:toolchains()
local toolchain_opt = table.copy(self:extraconf("toolchains", name))
toolchain_opt.arch = self:arch()
toolchain_opt.plat = self:plat()
+ toolchain_opt.namespace = self:namespace()
local toolchain_inst, errors = toolchain.load(name, toolchain_opt)
-- attempt to load toolchain from project
if not toolchain_inst and target._project() then
@@ -2478,9 +2547,9 @@ end
function _instance:tool(toolkind)
-- we cannot get tool in on_load, because target:toolchains() has been not checked in configuration stage.
if not self._LOADED_AFTER then
- os.raise("we cannot get tool(%s) before target(%s) is loaded, maybe it is called on_load(), please call it in on_config().", toolkind, self:name())
+ os.raise("we cannot get tool(%s) before target(%s) is loaded, maybe it is called on_load(), please call it in on_config().", toolkind, self:fullname())
end
- return toolchain.tool(self:toolchains(), toolkind, {cachekey = "target_" .. self:name(), plat = self:plat(), arch = self:arch(),
+ return toolchain.tool(self:toolchains(), toolkind, {cachekey = "target_" .. self:fullname(), plat = self:plat(), arch = self:arch(),
before_get = function()
-- get program from set_toolset
local program = self:get("toolset." .. toolkind)
@@ -2517,7 +2586,7 @@ end
-- get tool configuration from the toolchains
function _instance:toolconfig(name)
- return toolchain.toolconfig(self:toolchains(), name, {cachekey = "target_" .. self:name(), plat = self:plat(), arch = self:arch(),
+ return toolchain.toolconfig(self:toolchains(), name, {cachekey = "target_" .. self:fullname(), plat = self:plat(), arch = self:arch(),
after_get = function(toolchain_inst)
-- get flags from target.on_xxflags()
local script = toolchain_inst:get("target.on_" .. name)
diff --git a/xmake/core/sandbox/modules/get_config.lua b/xmake/core/sandbox/modules/get_config.lua
index 7fbd16a58..fd09c02e3 100644
--- a/xmake/core/sandbox/modules/get_config.lua
+++ b/xmake/core/sandbox/modules/get_config.lua
@@ -18,6 +18,19 @@
-- @file get_config.lua
--
--- return module
-return require("project/config").get
+local config = require("project/config")
+local sandbox = require("sandbox/sandbox")
+
+return function (name)
+ local namespace
+ local instance = sandbox.instance()
+ if instance then
+ namespace = instance:namespace()
+ end
+ local value = config.get(name)
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ return value
+end
diff --git a/xmake/core/sandbox/modules/has_config.lua b/xmake/core/sandbox/modules/has_config.lua
index c6b68fc9e..468144754 100644
--- a/xmake/core/sandbox/modules/has_config.lua
+++ b/xmake/core/sandbox/modules/has_config.lua
@@ -18,6 +18,25 @@
-- @file has_config.lua
--
--- return module
-return require("project/config").has
+local config = require("project/config")
+local sandbox = require("sandbox/sandbox")
+
+return function (...)
+ local namespace
+ local instance = sandbox.instance()
+ if instance then
+ namespace = instance:namespace()
+ end
+ local names = table.pack(...)
+ for _, name in ipairs(names) do
+ local value = config.get(name)
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ if value then
+ return true
+ end
+ end
+ return false
+end
diff --git a/xmake/core/sandbox/modules/has_package.lua b/xmake/core/sandbox/modules/has_package.lua
index 8d6c8ec3f..cb5d2822e 100644
--- a/xmake/core/sandbox/modules/has_package.lua
+++ b/xmake/core/sandbox/modules/has_package.lua
@@ -23,8 +23,19 @@ return function (...)
require("sandbox/modules/import/core/sandbox/module").import("core.project.project")
local requires = project.required_packages()
if requires then
- for _, name in ipairs(table.join(...)) do
- local pkg = requires[name]
+ for _, packagename in ipairs(table.join(...)) do
+ local pkg = requires[packagename]
+ -- attempt to get package with namespace
+ if pkg == nil and packagename:find("::", 1, true) then
+ local parts = packagename:split("::", {plain = true})
+ local namespace_pkg = requires[parts[#parts]]
+ if namespace_pkg and namespace_pkg:namespace() then
+ local fullname = namespace_pkg:fullname()
+ if fullname:endswith(packagename) then
+ pkg = namespace_pkg
+ end
+ end
+ end
if pkg and pkg:enabled() then
return true
end
diff --git a/xmake/core/sandbox/modules/import/core/base/process.lua b/xmake/core/sandbox/modules/import/core/base/process.lua
index 884ae9ebe..531ae0bd6 100644
--- a/xmake/core/sandbox/modules/import/core/base/process.lua
+++ b/xmake/core/sandbox/modules/import/core/base/process.lua
@@ -25,8 +25,8 @@ local raise = require("sandbox/modules/raise")
local vformat = require("sandbox/modules/vformat")
-- define module
-local sandbox_core_base_process = sandbox_core_base_process or {}
-local sandbox_core_base_instance = sandbox_core_base_instance or {}
+local sandbox_core_base_process = sandbox_core_base_process or {}
+local sandbox_core_base_instance = sandbox_core_base_instance or {}
sandbox_core_base_process._subprocess = sandbox_core_base_process._subprocess or process._subprocess
-- wait subprocess
diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua
index bada906d4..61b538bb1 100644
--- a/xmake/core/sandbox/modules/import/core/project/project.lua
+++ b/xmake/core/sandbox/modules/import/core/project/project.lua
@@ -71,6 +71,7 @@ sandbox_core_project.tmpdir = project.tmpdir
sandbox_core_project.tmpfile = project.tmpfile
sandbox_core_project.is_loaded = project.is_loaded
sandbox_core_project.apis = project.apis
+sandbox_core_project.namespaces = project.namespaces
-- check project options
function sandbox_core_project.check_options()
@@ -98,15 +99,15 @@ function sandbox_core_project.check_options()
if opt then
-- check deps of this option first
for _, dep in ipairs(opt:orderdeps()) do
- if not checked[dep:name()] then
+ if not checked[dep:fullname()] then
dep:check()
- checked[dep:name()] = true
+ checked[dep:fullname()] = true
end
end
-- check this option
- if not checked[opt:name()] then
+ if not checked[opt:fullname()] then
opt:check()
- checked[opt:name()] = true
+ checked[opt:fullname()] = true
end
end
end
diff --git a/xmake/core/sandbox/modules/is_config.lua b/xmake/core/sandbox/modules/is_config.lua
index 017f707f4..9cc4ec18b 100644
--- a/xmake/core/sandbox/modules/is_config.lua
+++ b/xmake/core/sandbox/modules/is_config.lua
@@ -18,6 +18,19 @@
-- @file is_config.lua
--
--- return module
-return require("project/config").is_value
+local config = require("project/config")
+local sandbox = require("sandbox/sandbox")
+
+return function (name, ...)
+ local namespace
+ local instance = sandbox.instance()
+ if instance then
+ namespace = instance:namespace()
+ end
+ local value = config.get(name)
+ if value == nil and namespace then
+ value = config.get(namespace .. "::" .. name)
+ end
+ return config._is_value(value, ...)
+end
diff --git a/xmake/core/sandbox/sandbox.lua b/xmake/core/sandbox/sandbox.lua
index 1e0817a4e..2d624da98 100644
--- a/xmake/core/sandbox/sandbox.lua
+++ b/xmake/core/sandbox/sandbox.lua
@@ -79,12 +79,8 @@ function sandbox._traceback(errors)
else
results = results .. string.format(" [%s:%d]:\n", info.short_src, info.currentline)
end
-
- -- next
level = level + 1
end
-
- -- ok?
return results
end
@@ -111,28 +107,20 @@ function sandbox._new()
-- bind instance to the public script envirnoment
instance:bind(instance._PUBLIC)
-
- -- ok?
return instance
end
-- new a sandbox instance with the given script
-function sandbox.new(script, filter, rootdir)
-
- -- check
- assert(script)
+function sandbox.new(script, opt)
+ opt = opt or {}
-- new instance
local self = sandbox._new()
-
- -- check
assert(self and self._PUBLIC and self._PRIVATE)
- -- save filter
- self._PRIVATE._FILTER = filter
-
- -- save root directory
- self._PRIVATE._ROOTDIR = rootdir
+ self._PRIVATE._FILTER = opt.filter
+ self._PRIVATE._ROOTDIR = opt.rootdir
+ self._PRIVATE._NAMESPACE = opt.namespace
-- invalid script?
if type(script) ~= "function" then
@@ -189,23 +177,17 @@ function sandbox:fork(script, rootdir)
-- init a new sandbox instance
local instance = sandbox._new()
-
- -- check
assert(instance and instance._PUBLIC and instance._PRIVATE)
- -- inherit the filter
instance._PRIVATE._FILTER = self:filter()
-
- -- inherit the root directory
instance._PRIVATE._ROOTDIR = rootdir or self:rootdir()
+ instance._PRIVATE._NAMESPACE = self:namespace()
-- bind public scope
if script then
setfenv(script, instance._PUBLIC)
instance._PRIVATE._SCRIPT = script
end
-
- -- ok?
return instance
end
@@ -257,6 +239,12 @@ function sandbox:rootdir()
return self._PRIVATE._ROOTDIR
end
+-- get current namespace
+function sandbox:namespace()
+ assert(self and self._PRIVATE)
+ return self._PRIVATE._NAMESPACE
+end
+
-- get current instance in the sandbox modules
function sandbox.instance(script)
diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua
index 29bd5a09f..a19413d34 100644
--- a/xmake/core/tool/toolchain.lua
+++ b/xmake/core/tool/toolchain.lua
@@ -42,7 +42,12 @@ local sandbox_module = require("sandbox/modules/import/core/sandbox/module")
-- new an instance
function _instance.new(name, info, cachekey, is_builtin, configs)
local instance = table.inherit(_instance)
- instance._NAME = name
+ local parts = name:split("::", {plain = true})
+ instance._NAME = parts[#parts]
+ table.remove(parts)
+ if #parts > 0 then
+ instance._NAMESPACE = table.concat(parts, "::")
+ end
instance._INFO = info
instance._IS_BUILTIN = is_builtin
instance._CACHE = toolchain._localcache()
@@ -68,6 +73,17 @@ function _instance:name()
return self._NAME
end
+-- get the namespace
+function _instance:namespace()
+ return self._NAMESPACE
+end
+
+-- get the full name
+function _instance:fullname()
+ local namespace = self:namespace()
+ return namespace and namespace .. "::" .. self:name() or self:name()
+end
+
-- get toolchain platform
function _instance:plat()
return self._PLAT or self:config("plat")