diff options
| author | ruki <[email protected]> | 2025-01-09 10:19:14 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-01-09 10:19:14 +0800 |
| commit | 8e24b5a44dcffbee1444d715909a64014e11e866 (patch) | |
| tree | a2f0aaf7b582dae30d4db636efd199ccb158e0d8 /xmake/core | |
| parent | 1cf6a7f479837b471a5f91410359d86983828e6a (diff) | |
| parent | 6317ffd0fe312360eb5f6e079320c01c95870ad0 (diff) | |
Merge pull request #6001 from xmake-io/namespace
Support for namespace
Diffstat (limited to 'xmake/core')
| -rw-r--r-- | xmake/core/base/cli.lua | 4 | ||||
| -rw-r--r-- | xmake/core/base/interpreter.lua | 215 | ||||
| -rw-r--r-- | xmake/core/base/private/instance_deps.lua | 12 | ||||
| -rw-r--r-- | xmake/core/base/task.lua | 31 | ||||
| -rw-r--r-- | xmake/core/package/package.lua | 66 | ||||
| -rw-r--r-- | xmake/core/project/config.lua | 51 | ||||
| -rw-r--r-- | xmake/core/project/option.lua | 68 | ||||
| -rw-r--r-- | xmake/core/project/package.lua | 13 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 120 | ||||
| -rw-r--r-- | xmake/core/project/rule.lua | 24 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 111 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/get_config.lua | 17 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/has_config.lua | 23 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/has_package.lua | 15 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/process.lua | 4 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/project/project.lua | 9 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/is_config.lua | 17 | ||||
| -rw-r--r-- | xmake/core/sandbox/sandbox.lua | 36 | ||||
| -rw-r--r-- | xmake/core/tool/toolchain.lua | 18 |
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") |
