summaryrefslogtreecommitdiff
path: root/xmake/plugins
diff options
context:
space:
mode:
authorruki <[email protected]>2025-11-14 22:20:39 +0800
committerGitHub <[email protected]>2025-11-14 22:20:39 +0800
commit100900c957fa0db180ccaf5f1f157a78e9db665d (patch)
tree42bdffc19ea83d2f4b72af9a931ced20f2c0eaac /xmake/plugins
parent7b66ccfbd2db6925d6ccba7e56273396cb66b416 (diff)
parentd066068a571d6e6515e56270374e96518d20eaf0 (diff)
Merge pull request #7024 from xmake-io/show
Add json output for `xmake show -t target`
Diffstat (limited to 'xmake/plugins')
-rw-r--r--xmake/plugins/show/info/basic.lua142
-rw-r--r--xmake/plugins/show/info/target.lua228
-rw-r--r--xmake/plugins/show/showlist.lua7
-rw-r--r--xmake/plugins/show/xmake.lua1
4 files changed, 293 insertions, 85 deletions
diff --git a/xmake/plugins/show/info/basic.lua b/xmake/plugins/show/info/basic.lua
index 440e6768a..4ad14fe98 100644
--- a/xmake/plugins/show/info/basic.lua
+++ b/xmake/plugins/show/info/basic.lua
@@ -21,51 +21,127 @@
-- imports
import("core.base.option")
import("core.base.global")
+import("core.base.json")
import("core.project.config")
import("core.project.project")
import("core.package.package")
--- show basic info
-function main()
+function _show_xmake_info(opt, result)
+ local json_enabled = opt and opt.json
+ local info = {
+ version = tostring(xmake.version()),
+ host = {os = os.host(), arch = os.arch()},
+ programdir = xmake.programdir(),
+ programfile = xmake.programfile(),
+ globaldir = global.directory(),
+ tmpdir = os.tmpdir(),
+ workingdir = os.workingdir(),
+ packagedir = package.installdir(),
+ packagedir_cache = package.cachedir()
+ }
+ if json_enabled then
+ result = result or {}
+ result.xmake = info
+ else
+ print("The information of xmake:")
+ cprint(" ${color.dump.string}version${clear}: %s", info.version)
+ cprint(" ${color.dump.string}host${clear}: %s/%s", info.host.os, info.host.arch)
+ cprint(" ${color.dump.string}programdir${clear}: %s", info.programdir)
+ cprint(" ${color.dump.string}programfile${clear}: %s", info.programfile)
+ cprint(" ${color.dump.string}globaldir${clear}: %s", info.globaldir)
+ cprint(" ${color.dump.string}tmpdir${clear}: %s", info.tmpdir)
+ cprint(" ${color.dump.string}workingdir${clear}: %s", info.workingdir)
+ cprint(" ${color.dump.string}packagedir${clear}: %s", info.packagedir)
+ cprint(" ${color.dump.string}packagedir(cache)${clear}: %s", info.packagedir_cache)
+ print("")
+ end
+ return result
+end
- -- get target
- config.load()
+function _show_project_info(opt, result)
+ local json_enabled = opt and opt.json
+ local projectfile = os.projectfile()
+ if not os.isfile(projectfile) then
+ return result
+ end
- -- show xmake information
- print("The information of xmake:")
- cprint(" ${color.dump.string}version${clear}: %s", xmake.version())
- cprint(" ${color.dump.string}host${clear}: %s/%s", os.host(), os.arch())
- cprint(" ${color.dump.string}programdir${clear}: %s", xmake.programdir())
- cprint(" ${color.dump.string}programfile${clear}: %s", xmake.programfile())
- cprint(" ${color.dump.string}globaldir${clear}: %s", global.directory())
- cprint(" ${color.dump.string}tmpdir${clear}: %s", os.tmpdir())
- cprint(" ${color.dump.string}workingdir${clear}: %s", os.workingdir())
- cprint(" ${color.dump.string}packagedir${clear}: %s", package.installdir())
- cprint(" ${color.dump.string}packagedir(cache)${clear}: %s", package.cachedir())
- print("")
+ local info = {
+ configdir = config.directory(),
+ projectdir = os.projectdir(),
+ projectfile = projectfile
+ }
+ local name = project.name()
+ if name then
+ info.name = name
+ end
+ local project_version = project.version()
+ if project_version ~= nil then
+ info.version = tostring(project_version)
+ end
+ local plat = config.plat()
+ if plat then
+ info.plat = plat
+ end
+ local arch = config.arch()
+ if arch then
+ info.arch = arch
+ end
+ local mode = config.mode()
+ if mode then
+ info.mode = mode
+ end
+ local builddir = config.builddir()
+ if builddir then
+ info.builddir = builddir
+ end
- local projectfile = os.projectfile()
- if os.isfile(projectfile) then
- print("The information of project: %s", project.name() and project.name() or "")
- local version = project.version()
- if version then
- cprint(" ${color.dump.string}version${clear}: %s", version)
+ if json_enabled then
+ result = result or {}
+ result.project = info
+ else
+ print("The information of project: %s", info.name or "")
+ if info.version then
+ cprint(" ${color.dump.string}version${clear}: %s", info.version)
end
- if config.plat() then
- cprint(" ${color.dump.string}plat${clear}: %s", config.plat())
+ if info.plat then
+ cprint(" ${color.dump.string}plat${clear}: %s", info.plat)
end
- if config.arch() then
- cprint(" ${color.dump.string}arch${clear}: %s", config.arch())
+ if info.arch then
+ cprint(" ${color.dump.string}arch${clear}: %s", info.arch)
end
- if config.mode() then
- cprint(" ${color.dump.string}mode${clear}: %s", config.mode())
+ if info.mode then
+ cprint(" ${color.dump.string}mode${clear}: %s", info.mode)
end
- if config.builddir() then
- cprint(" ${color.dump.string}builddir${clear}: %s", config.builddir())
+ if info.builddir then
+ cprint(" ${color.dump.string}builddir${clear}: %s", info.builddir)
end
- cprint(" ${color.dump.string}configdir${clear}: %s", config.directory())
- cprint(" ${color.dump.string}projectdir${clear}: %s", os.projectdir())
- cprint(" ${color.dump.string}projectfile${clear}: %s", projectfile)
+ cprint(" ${color.dump.string}configdir${clear}: %s", info.configdir)
+ cprint(" ${color.dump.string}projectdir${clear}: %s", info.projectdir)
+ cprint(" ${color.dump.string}projectfile${clear}: %s", info.projectfile)
print("")
end
+ return result
+end
+
+-- show basic info
+function main()
+
+ config.load()
+
+ local opt = {
+ json = option.get("json"),
+ pretty = option.get("pretty")
+ }
+ local result = opt.json and {} or nil
+
+ result = _show_xmake_info(opt, result)
+ result = _show_project_info(opt, result)
+
+ if opt.json then
+ local json_opt
+ if opt.pretty then
+ json_opt = {pretty = true, orderkeys = true}
+ end
+ print(json.encode(result or {}, json_opt))
+ end
end
diff --git a/xmake/plugins/show/info/target.lua b/xmake/plugins/show/info/target.lua
index d5ddfbe76..62d8b6ddd 100644
--- a/xmake/plugins/show/info/target.lua
+++ b/xmake/plugins/show/info/target.lua
@@ -20,34 +20,57 @@
-- imports
import("core.base.option")
+import("core.base.json")
import("core.base.hashset")
import("core.project.config")
import("core.language.language")
import("private.detect.check_targetname")
--- get source info string
-function _get_sourceinfo_str(target, name, item, opt)
+-- get source info data
+function _get_sourceinfo(target, name, item, opt)
opt = opt or {}
local sourceinfo = target:sourceinfo(name, item)
+ local tips = opt.tips
if sourceinfo then
- local tips = opt.tips
- if tips then
- tips = tips .. " -> "
- end
+ return {
+ file = sourceinfo.file,
+ line = sourceinfo.line,
+ tips = tips
+ }
+ elseif tips then
+ return {tips = tips}
+ end
+end
+
+-- format source info string with color
+function _format_sourceinfo(sourceinfo)
+ if not sourceinfo then
+ return ""
+ end
+ local tips = sourceinfo.tips
+ if tips then
+ tips = tips .. " -> "
+ end
+ if sourceinfo.file then
return string.format(" ${dim}-> %s%s:%s${clear}", tips or "", sourceinfo.file or "", sourceinfo.line or -1)
- elseif opt.tips then
- return string.format(" ${dim}-> %s${clear}", opt.tips)
+ elseif tips then
+ return string.format(" ${dim}-> %s${clear}", tips)
end
return ""
end
+-- get source info string
+function _get_sourceinfo_str(target, name, item, opt)
+ return _format_sourceinfo(_get_sourceinfo(target, name, item, opt))
+end
+
-- get values from target options
function _get_values_from_opts(target, name)
local values = {}
for _, opt_ in ipairs(target:orderopts()) do
for _, value in ipairs(opt_:get(name)) do
local tips = string.format("option(%s)", opt_:name())
- values[value] = _get_sourceinfo_str(opt_, name, value, {tips = tips})
+ values[value] = _get_sourceinfo(opt_, name, value, {tips = tips})
end
end
return values
@@ -78,7 +101,8 @@ function _get_values_from_pkgs(target, name)
local info = components[component_name]
if info then
for _, value in ipairs(info[name]) do
- values[value] = string.format(" -> package(%s)", pkg:fullname())
+ local tips = string.format("package(%s)", pkg:fullname())
+ values[value] = {tips = tips}
end
else
local components_str = table.concat(table.wrap(configinfo.components), ", ")
@@ -90,12 +114,14 @@ function _get_values_from_pkgs(target, name)
-- e.g. `add_packages("xxx", {links = "xxx"})`
elseif configinfo and configinfo[name] then
for _, value in ipairs(configinfo[name]) do
- values[value] = _get_sourceinfo_str(target, "packages", pkg:name())
+ local sourceinfo = _get_sourceinfo(target, "packages", pkg:name())
+ values[value] = sourceinfo
end
else
-- get values from the builtin package configs
for _, value in ipairs(pkg:get(name)) do
- values[value] = string.format(" -> package(%s)", pkg:fullname())
+ local tips = string.format("package(%s)", pkg:fullname())
+ values[value] = {tips = tips}
end
end
end
@@ -112,18 +138,21 @@ function _get_values_from_deps(target, name)
local depinherit = target:extraconf("deps", dep:name(), "inherit")
if depinherit == nil or depinherit then
for _, value in ipairs(dep:get(name, {interface = true})) do
- values[value] = string.format(" -> dep(%s)", dep:name())
+ local tips = string.format("dep(%s)", dep:name())
+ values[value] = {tips = tips}
end
local values_chunks = dep:get_from(name, "option::*", {interface = true})
for _, values_chunk in ipairs(values_chunks) do
for _, value in ipairs(values_chunk) do
- values[value] = string.format(" -> dep(%s) -> options", dep:name())
+ local tips = string.format("dep(%s) -> options", dep:name())
+ values[value] = {tips = tips}
end
end
values_chunks = dep:get_from(name, "package::*", {interface = true})
for _, values_chunk in ipairs(values_chunks) do
for _, value in ipairs(values_chunk) do
- values[value] = string.format(" -> dep(%s) -> packages", dep:name())
+ local tips = string.format("dep(%s) -> packages", dep:name())
+ values[value] = {tips = tips}
end
end
end
@@ -131,27 +160,36 @@ function _get_values_from_deps(target, name)
return values
end
--- show target information
-function _show_target(target)
- print("The information of target(%s):", target:name())
- cprint(" ${color.dump.string}at${clear}: %s", path.join(target:scriptdir(), "xmake.lua"))
- cprint(" ${color.dump.string}kind${clear}: %s", target:kind())
+function _collect_target_info(target)
+ local info = {
+ name = target:name(),
+ at = path.join(target:scriptdir(), "xmake.lua"),
+ kind = target:kind()
+ }
local targetfile = target:targetfile()
if targetfile then
- cprint(" ${color.dump.string}targetfile${clear}: %s", targetfile)
+ info.targetfile = targetfile
end
local deps = target:get("deps")
if deps then
- cprint(" ${color.dump.string}deps${clear}:")
+ local entries = {}
for _, dep in ipairs(deps) do
- cprint(" ${color.dump.reference}->${clear} %s%s", dep, _get_sourceinfo_str(target, "deps", dep))
+ local entry = {name = dep, source = _get_sourceinfo(target, "deps", dep)}
+ table.insert(entries, entry)
+ end
+ if #entries > 0 then
+ info.deps = entries
end
end
local rules = target:get("rules")
if rules then
- cprint(" ${color.dump.string}rules${clear}:")
+ local entries = {}
for _, value in ipairs(rules) do
- cprint(" ${color.dump.reference}->${clear} %s%s", value, _get_sourceinfo_str(target, "rules", value))
+ local entry = {name = value, source = _get_sourceinfo(target, "rules", value)}
+ table.insert(entries, entry)
+ end
+ if #entries > 0 then
+ info.rules = entries
end
end
local options = {}
@@ -161,18 +199,25 @@ function _show_target(target)
end
end
if #options > 0 then
- cprint(" ${color.dump.string}options${clear}:")
+ local entries = {}
for _, value in ipairs(options) do
- cprint(" ${color.dump.reference}->${clear} %s%s", value, _get_sourceinfo_str(target, "options", value))
+ table.insert(entries, {name = value, source = _get_sourceinfo(target, "options", value)})
+ end
+ if #entries > 0 then
+ info.options = entries
end
end
local packages = target:get("packages")
if packages then
- cprint(" ${color.dump.string}packages${clear}:")
+ local entries = {}
for _, value in ipairs(packages) do
- cprint(" ${color.dump.reference}->${clear} %s%s", value, _get_sourceinfo_str(target, "packages", value))
+ table.insert(entries, {name = value, source = _get_sourceinfo(target, "packages", value)})
+ end
+ if #entries > 0 then
+ info.packages = entries
end
end
+ info.api_entries = {}
for _, apiname in ipairs(table.join(language.apis().values, language.apis().paths)) do
if apiname:startswith("target.") then
local valuename = apiname:split('.add_', {plain = true})[2]
@@ -181,38 +226,44 @@ function _show_target(target)
local values = table.unique(table.wrap(target:get(valuename)))
if #values > 0 then
for _, value in ipairs(values) do
- table.insert(results, {value = value, sourceinfo = _get_sourceinfo_str(target, valuename, value)})
+ local sourceinfo = _get_sourceinfo(target, valuename, value)
+ table.insert(results, {value = value, source = sourceinfo})
end
end
local values_from_opts = _get_values_from_opts(target, valuename)
for value, sourceinfo in pairs(values_from_opts) do
- table.insert(results, {value = value, sourceinfo = sourceinfo})
+ table.insert(results, {value = value, source = sourceinfo})
end
local values_from_pkgs = _get_values_from_pkgs(target, valuename)
for value, sourceinfo in pairs(values_from_pkgs) do
- table.insert(results, {value = value, sourceinfo = sourceinfo})
+ table.insert(results, {value = value, source = sourceinfo})
end
local values_from_deps = _get_values_from_deps(target, valuename)
for value, sourceinfo in pairs(values_from_deps) do
- table.insert(results, {value = value, sourceinfo = sourceinfo})
+ table.insert(results, {value = value, source = sourceinfo})
end
if #results > 0 then
- cprint(" ${color.dump.string}%s${clear}:", valuename)
+ local entries = {}
for _, result in ipairs(results) do
- cprint(" ${color.dump.reference}->${clear} %s%s", result.value, result.sourceinfo)
+ table.insert(entries, result)
end
+ info[valuename] = entries
+ table.insert(info.api_entries, {name = valuename, entries = entries})
end
end
end
end
local files = target:get("files")
if files then
- cprint(" ${color.dump.string}files${clear}:")
+ local entries = {}
for _, file in ipairs(files) do
if not file:startswith("__remove_") then
- cprint(" ${color.dump.reference}->${clear} %s%s", file, _get_sourceinfo_str(target, "files", file))
+ table.insert(entries, {path = file, source = _get_sourceinfo(target, "files", file)})
end
end
+ if #entries > 0 then
+ info.files = entries
+ end
end
local sourcekinds = hashset.new()
for _, sourcebatch in pairs(target:sourcebatches()) do
@@ -223,25 +274,87 @@ function _show_target(target)
for _, sourcekind in sourcekinds:keys() do
local compinst = target:compiler(sourcekind)
if compinst then
- cprint(" ${color.dump.string}compiler (%s)${clear}: %s", sourcekind, compinst:program())
- cprint(" ${color.dump.reference}->${clear} %s", os.args(compinst:compflags()))
+ info.compilers = info.compilers or {}
+ table.insert(info.compilers, {
+ sourcekind = sourcekind,
+ program = compinst:program(),
+ flags = os.args(compinst:compflags()),
+ flags_with_target = os.args(compinst:compflags({target = target}))
+ })
end
end
local linker = targetfile and target:linker()
if linker then
- cprint(" ${color.dump.string}linker (%s)${clear}: %s", linker:kind(), linker:program())
- cprint(" ${color.dump.reference}->${clear} %s", os.args(linker:linkflags()))
+ info.linker = {
+ kind = linker:kind(),
+ program = linker:program(),
+ flags = os.args(linker:linkflags()),
+ flags_with_target = os.args(linker:linkflags({target = target}))
+ }
end
- for _, sourcekind in sourcekinds:keys() do
- local compinst = target:compiler(sourcekind)
- if compinst then
- cprint(" ${color.dump.string}compflags (%s)${clear}:", sourcekind)
- cprint(" ${color.dump.reference}->${clear} %s", os.args(compinst:compflags({target = target})))
+ return info
+end
+
+function _print_entries(label, items, formatter)
+ if not items or #items == 0 then
+ return
+ end
+ cprint(" ${color.dump.string}%s${clear}:", label)
+ for _, item in ipairs(items) do
+ local text, source = formatter(item)
+ cprint(" ${color.dump.reference}->${clear} %s%s", text, source or "")
+ end
+end
+
+function _print_target_info(info)
+ print("The information of target(%s):", info.name)
+ cprint(" ${color.dump.string}at${clear}: %s", info.at)
+ cprint(" ${color.dump.string}kind${clear}: %s", info.kind)
+ if info.targetfile then
+ cprint(" ${color.dump.string}targetfile${clear}: %s", info.targetfile)
+ end
+ _print_entries("deps", info.deps, function(item)
+ return item.name, _format_sourceinfo(item.source)
+ end)
+ _print_entries("rules", info.rules, function(item)
+ return item.name, _format_sourceinfo(item.source)
+ end)
+ _print_entries("options", info.options, function(item)
+ return item.name, _format_sourceinfo(item.source)
+ end)
+ _print_entries("packages", info.packages, function(item)
+ return item.name, _format_sourceinfo(item.source)
+ end)
+ if info.api_entries then
+ for _, entry in ipairs(info.api_entries) do
+ _print_entries(entry.name, entry.entries, function(item)
+ local source = _format_sourceinfo(item.source)
+ return item.value, source
+ end)
end
end
- if linker then
- cprint(" ${color.dump.string}linkflags (%s)${clear}:", linker:kind())
- cprint(" ${color.dump.reference}->${clear} %s", os.args(linker:linkflags({target = target})))
+ if info.files then
+ _print_entries("files", info.files, function(item)
+ return item.path, _format_sourceinfo(item.source)
+ end)
+ end
+ if info.compilers then
+ for _, compiler in ipairs(info.compilers) do
+ cprint(" ${color.dump.string}compiler (%s)${clear}: %s", compiler.sourcekind, compiler.program)
+ if compiler.flags then
+ cprint(" ${color.dump.reference}->${clear} %s", compiler.flags)
+ end
+ end
+ for _, compiler in ipairs(info.compilers) do
+ cprint(" ${color.dump.string}compflags (%s)${clear}:", compiler.sourcekind)
+ cprint(" ${color.dump.reference}->${clear} %s", compiler.flags_with_target)
+ end
+ end
+ if info.linker then
+ cprint(" ${color.dump.string}linker (%s)${clear}: %s", info.linker.kind, info.linker.program)
+ cprint(" ${color.dump.reference}->${clear} %s", info.linker.flags)
+ cprint(" ${color.dump.string}linkflags (%s)${clear}:", info.linker.kind)
+ cprint(" ${color.dump.reference}->${clear} %s", info.linker.flags_with_target)
end
end
@@ -249,8 +362,21 @@ function main(name)
-- get target
config.load()
+ local opt = {
+ json = option.get("json"),
+ pretty = option.get("pretty")
+ }
local target = assert(check_targetname(name))
- -- show target information
- _show_target(target)
+ local info = _collect_target_info(target)
+ if opt.json then
+ info.api_entries = nil
+ local json_opt
+ if opt.pretty then
+ json_opt = {pretty = true, orderkeys = true}
+ end
+ print(json.encode(info or {}, json_opt))
+ else
+ _print_target_info(info)
+ end
end
diff --git a/xmake/plugins/show/showlist.lua b/xmake/plugins/show/showlist.lua
index 9dadb59c6..205ae21ed 100644
--- a/xmake/plugins/show/showlist.lua
+++ b/xmake/plugins/show/showlist.lua
@@ -40,7 +40,12 @@ function _show_text(values)
end
function _show_json(values)
- print(json.encode(values))
+ local opt = {}
+ if option.get("pretty") then
+ opt.pretty = true
+ opt.orderkeys = true
+ end
+ print(json.encode(values, opt))
end
function main(values)
diff --git a/xmake/plugins/show/xmake.lua b/xmake/plugins/show/xmake.lua
index 475a771b8..331aeb468 100644
--- a/xmake/plugins/show/xmake.lua
+++ b/xmake/plugins/show/xmake.lua
@@ -31,6 +31,7 @@ task("show")
end},
{'g', "group", "kv", nil, "Filter targets by the given group name."},
{nil, "json", "k", false, "Show information with json format."},
+ {nil, "pretty", "k", false, "Enable pretty formatted json output."},
{'t', "target", "kv", nil, "Show the information of the given target.",
values = function (complete, opt)
return import("private.utils.complete_helper.targets")(complete, opt)