summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-06-18 08:59:11 +0800
committerGitHub <[email protected]>2026-06-18 08:59:11 +0800
commit9b8df1e3c6bf7aa841c3c62f8f80d5016690367b (patch)
tree337586fdbc65cf15d539be45899fb8c61020ef62
parentba2df770b8430a8f8e593d34dc05de051a59a1bd (diff)
parent02a69e7a3e0442a750c33eae77dc5feb2e5ff655 (diff)
Merge pull request #7607 from xmake-io/targets
Support multiple targets
-rw-r--r--xmake/actions/build/main.lua22
-rw-r--r--xmake/actions/build/xmake.lua6
-rw-r--r--xmake/actions/clean/main.lua20
-rw-r--r--xmake/actions/clean/xmake.lua11
-rw-r--r--xmake/actions/install/install.lua21
-rw-r--r--xmake/actions/install/install_admin.lua5
-rw-r--r--xmake/actions/install/main.lua28
-rw-r--r--xmake/actions/install/xmake.lua6
-rw-r--r--xmake/actions/package/local/main.lua20
-rw-r--r--xmake/actions/package/oldpkg/main.lua25
-rw-r--r--xmake/actions/package/remote/main.lua16
-rw-r--r--xmake/actions/package/xmake.lua6
-rw-r--r--xmake/actions/run/main.lua4
-rw-r--r--xmake/actions/uninstall/main.lua11
-rw-r--r--xmake/actions/uninstall/uninstall.lua21
-rw-r--r--xmake/actions/uninstall/uninstall_admin.lua12
-rw-r--r--xmake/actions/uninstall/xmake.lua6
-rw-r--r--xmake/modules/cli/amalgamate.lua4
-rw-r--r--xmake/modules/private/action/utils.lua62
-rw-r--r--xmake/modules/private/detect/check_targetnames.lua (renamed from xmake/modules/private/detect/check_targetname.lua)56
-rw-r--r--xmake/plugins/format/main.lua20
-rw-r--r--xmake/plugins/format/xmake.lua4
-rw-r--r--xmake/plugins/show/info/depgraph.lua4
-rw-r--r--xmake/plugins/show/info/target.lua4
-rw-r--r--xmake/rules/xcode/application/install.lua2
25 files changed, 225 insertions, 171 deletions
diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua
index aa8a8c089..2bc298cd1 100644
--- a/xmake/actions/build/main.lua
+++ b/xmake/actions/build/main.lua
@@ -38,10 +38,10 @@ import("private.cache.build_cache")
import("private.service.remote_build.action", {alias = "remote_build_action"})
import("private.utils.statistics")
import("private.action.utils", {alias = "action_utils"})
-import("private.detect.check_targetname")
+import("private.detect.check_targetnames")
-- try building it
-function _do_try_build(configfile, tool, trybuild, trybuild_detected, targetname)
+function _do_try_build(configfile, tool, trybuild, trybuild_detected, targetnames)
if configfile and tool and (trybuild or utils.confirm({default = true,
description = "${bright}" .. path.filename(configfile) .. "${clear} found, try building it or you can run `${bright}xmake f --trybuild=${clear}` to set buildsystem"})) then
if not trybuild then
@@ -59,9 +59,9 @@ function _try_build()
config.load()
-- rebuild it? do clean first
- local targetname = option.get("target")
+ local targetnames = action_utils.get_targets_and_group()
if option.get("rebuild") then
- task.run("clean", {target = targetname})
+ task.run("clean", {targets = targetnames})
end
-- get the buildsystem tool
@@ -76,14 +76,14 @@ function _try_build()
else
raise("unknown build tool: %s", trybuild)
end
- return _do_try_build(configfile, tool, trybuild, trybuild_detected, targetname)
+ return _do_try_build(configfile, tool, trybuild, trybuild_detected, targetnames)
else
for _, name in ipairs({"xrepo", "autoconf", "cmake", "meson", "scons", "bazel", "msbuild", "xcodebuild", "make", "ninja", "ndkbuild"}) do
tool = import("private.action.trybuild." .. name, {anonymous = true})
configfile = tool.detect()
if configfile then
trybuild_detected = name
- if _do_try_build(configfile, tool, trybuild, trybuild_detected, targetname) then
+ if _do_try_build(configfile, tool, trybuild, trybuild_detected, targetnames) then
return true
end
end
@@ -196,12 +196,12 @@ function main(opt)
project.lock()
-- config it first
- local targetname, group_pattern = action_utils.get_target_and_group()
+ local targetnames, group_pattern = action_utils.get_targets_and_group()
task.run("config", {}, {disable_dump = true})
- -- check target name
- if targetname then
- assert(check_targetname(targetname))
+ -- check target names
+ if targetnames then
+ assert(check_targetnames(targetnames))
end
-- enter project directory
@@ -212,7 +212,7 @@ function main(opt)
-- build targets
local build_time = os.mclock()
- build_targets(targetname, {group_pattern = group_pattern})
+ build_targets(targetnames, {group_pattern = group_pattern})
build_time = os.mclock() - build_time
-- leave project directory
diff --git a/xmake/actions/build/xmake.lua b/xmake/actions/build/xmake.lua
index 832a98725..655b28207 100644
--- a/xmake/actions/build/xmake.lua
+++ b/xmake/actions/build/xmake.lua
@@ -22,7 +22,7 @@ task("build")
set_category("main")
on_run("main")
set_menu {
- usage = "xmake [task] [options] [target]"
+ usage = "xmake [task] [options] [targets]"
, description = "Build targets if no given tasks."
, shortname = 'b'
, options =
@@ -53,7 +53,9 @@ task("build")
" - xmake --files='src/main.c" .. path.envsep() .. "src/test.c'" }
, {}
- , {nil, "target", "v", nil , "The target name. It will build all default targets if this parameter is not specified."
+ , {nil, "targets", "vs", nil , "The target names. It will build all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake build target1 target2 ..."
, values = function (complete, opt) return import("private.utils.complete_helper.targets")(complete, opt) end }
}
}
diff --git a/xmake/actions/clean/main.lua b/xmake/actions/clean/main.lua
index c4abe6956..6606ddc2f 100644
--- a/xmake/actions/clean/main.lua
+++ b/xmake/actions/clean/main.lua
@@ -29,7 +29,7 @@ import("core.platform.platform")
import("private.action.clean.remove_files")
import("target.action.clean", {alias = "_do_clean_target"})
import("private.service.remote_build.action", {alias = "remote_build_action"})
-import("private.detect.check_targetname")
+import("private.action.utils", {alias = "action_utils"})
-- on clean target
function _on_clean_target(target)
@@ -103,12 +103,12 @@ function _clean_targets(targets)
end
end
--- clean target
-function _clean(targetname)
- if targetname then
- local target = assert(check_targetname(targetname))
- _clean_target(target)
+-- clean targets
+function _clean(targetnames, group_pattern)
+ if (targetnames and #targetnames > 0) or group_pattern then
+ _clean_targets(action_utils.get_targets(targetnames, {group_pattern = group_pattern}))
else
+ -- clean all targets by default
_clean_targets(project.ordertargets())
end
end
@@ -163,14 +163,14 @@ function main()
-- lock the whole project
project.lock()
- -- get the target name
- local targetname = option.get("target")
+ -- get the target names and group pattern
+ local targetnames, group_pattern = action_utils.get_targets_and_group()
-- enter project directory
local oldir = os.cd(project.directory())
- -- clean target
- _clean(targetname)
+ -- clean targets
+ _clean(targetnames, group_pattern)
-- unlock the whole project
project.unlock()
diff --git a/xmake/actions/clean/xmake.lua b/xmake/actions/clean/xmake.lua
index 4f66dd205..980ee2b28 100644
--- a/xmake/actions/clean/xmake.lua
+++ b/xmake/actions/clean/xmake.lua
@@ -23,16 +23,23 @@ task("clean")
on_run("main")
set_menu {
- usage = "xmake clean|c [options] [target]"
+ usage = "xmake clean|c [options] [targets]"
, description = "Remove all binary and temporary files."
, shortname = 'c'
, options =
{
{'a', "all", "k", nil , "Clean all auto-generated files by xmake." }
+ , {'g', "group", "kv", nil , "Clean all targets of the given group. It support path pattern matching.",
+ "e.g.",
+ " xmake clean -g test",
+ " xmake clean -g test_*",
+ " xmake clean --group=benchmark/*" }
, {}
- , {nil, "target", "v", nil , "The target name. It will clean all default targets if this parameter is not specified."
+ , {nil, "targets", "vs", nil , "The target names. It will clean all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake clean target1 target2 ..."
, values = function (complete, opt) return import("private.utils.complete_helper.targets")(complete, opt) end }
}
}
diff --git a/xmake/actions/install/install.lua b/xmake/actions/install/install.lua
index 232f4f9c0..97db58f09 100644
--- a/xmake/actions/install/install.lua
+++ b/xmake/actions/install/install.lua
@@ -24,6 +24,7 @@ import("core.base.option")
import("core.project.rule")
import("core.project.project")
import("target.action.install", {alias = "_do_install_target"})
+import("private.action.utils", {alias = "action_utils"})
-- on install target
function _on_install_target(target)
@@ -111,20 +112,12 @@ function _install_targets(targets)
end
-- install targets
-function main(targetname, group_pattern)
- local targets = {}
- if targetname and not targetname:startswith("__") then
- local target = project.target(targetname)
- table.insert(targets, target)
- else
- for _, target in ipairs(project.ordertargets()) do
- local group = target:get("group")
- if (target:is_default() and not group_pattern) or targetname == "__all" or (group_pattern and group and group:match(group_pattern)) then
- table.insert(targets, target)
- end
- end
- end
+--
+-- @param targetnames the target names (table), a single target name, or the magic "__all"/"__def"
+--
+function main(targetnames, group_pattern)
+ local targets = action_utils.get_targets(targetnames, {group_pattern = group_pattern})
if #targets > 0 then
- _install_targets(table.unique(targets))
+ _install_targets(targets)
end
end
diff --git a/xmake/actions/install/install_admin.lua b/xmake/actions/install/install_admin.lua
index 22d6da524..61f02da89 100644
--- a/xmake/actions/install/install_admin.lua
+++ b/xmake/actions/install/install_admin.lua
@@ -27,6 +27,11 @@ import("install")
function main(targetname, group_pattern, installdir, bindir, libdir, includedir)
local verbose = option.get("verbose")
+
+ -- the targetname may be a list of target names joined with the path separator
+ if targetname and targetname:find(path.envsep(), 1, true) then
+ targetname = path.splitenv(targetname)
+ end
if group_pattern and #group_pattern == 0 then
group_pattern = nil
end
diff --git a/xmake/actions/install/main.lua b/xmake/actions/install/main.lua
index e6c8258fc..2cf7046b6 100644
--- a/xmake/actions/install/main.lua
+++ b/xmake/actions/install/main.lua
@@ -30,21 +30,10 @@ import("install")
import("private.action.utils", {alias = "action_utils"})
-- check targets
-function _check_targets(targetname, group_pattern)
+function _check_targets(targetnames, group_pattern)
-- get targets
- local targets = {}
- if targetname then
- table.insert(targets, project.target(targetname))
- else
- -- install default or all targets
- for _, target in pairs(project.targets()) do
- local group = target:get("group")
- if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then
- table.insert(targets, target)
- end
- end
- end
+ local targets = action_utils.get_targets(targetnames, {group_pattern = group_pattern})
-- filter and check targets with builtin-install script
local targetnames = {}
@@ -69,14 +58,17 @@ function main()
task.run("config", {require = false}, {disable_dump = true})
-- check targets first
- local targetname, group_pattern = action_utils.get_target_and_group()
- _check_targets(targetname, group_pattern)
+ local targetnames, group_pattern = action_utils.get_targets_and_group()
+ _check_targets(targetnames, group_pattern)
+
+ -- get the install targets argument, it may be a list of target names or the magic "__all"/"__def"
+ local targets_arg = targetnames or (option.get("all") and "__all" or "__def")
-- attempt to install directly
try
{
function ()
- install(targetname or (option.get("all") and "__all" or "__def"), group_pattern)
+ install(targets_arg, group_pattern)
cprint("${color.success}install ok!")
end,
@@ -90,7 +82,7 @@ function main()
local ok = try
{
function ()
- install(targetname or (option.get("all") and "__all" or "__def"), group_pattern)
+ install(targets_arg, group_pattern)
cprint("${color.success}install ok!")
return true
end
@@ -109,7 +101,7 @@ function main()
-- install target with administrator permission
sudo.execl(path.join(os.scriptdir(), "install_admin.lua"), {
- targetname or (option.get("all") and "__all" or "__def"),
+ type(targets_arg) == "table" and table.concat(targets_arg, path.envsep()) or targets_arg,
group_pattern or "", option.get("installdir") or "",
option.get("bindir"),
option.get("libdir"),
diff --git a/xmake/actions/install/xmake.lua b/xmake/actions/install/xmake.lua
index 3ef6a22c3..679ddbc81 100644
--- a/xmake/actions/install/xmake.lua
+++ b/xmake/actions/install/xmake.lua
@@ -22,7 +22,7 @@ task("install")
set_category("action")
on_run("main")
set_menu {
- usage = "xmake install|i [options] [target]",
+ usage = "xmake install|i [options] [targets]",
description = "Package and install the target binary files.",
shortname = 'i',
options = {
@@ -47,7 +47,9 @@ task("install")
{},
{nil, "admin", "k", nil , "Try to request administrator permission to install"},
{},
- {nil, "target", "v", nil , "The target name. It will install all default targets if this parameter is not specified.",
+ {nil, "targets", "vs", nil , "The target names. It will install all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake install target1 target2 ...",
values = function (complete, opt)
return import("private.utils.complete_helper.targets")(complete, opt)
end}
diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua
index 408b9ad76..97b2cae37 100644
--- a/xmake/actions/package/local/main.lua
+++ b/xmake/actions/package/local/main.lua
@@ -25,7 +25,7 @@ import("core.project.rule")
import("core.project.config")
import("core.project.project")
import("target.action.install")
-import("private.detect.check_targetname")
+import("private.action.utils", {alias = "action_utils"})
-- get library deps
function _get_librarydeps(target)
@@ -223,23 +223,15 @@ function main()
-- lock the whole project
project.lock()
- -- get the target name
- local targetname = option.get("target")
+ -- get the target names
+ local targetnames = option.get("targets")
-- build it first
- task.run("build", {target = targetname, all = option.get("all")})
+ task.run("build", {targets = targetnames, all = option.get("all")})
- -- package the given target?
- if targetname then
- local target = assert(check_targetname(targetname))
+ -- package the given targets
+ for _, target in ipairs(action_utils.get_targets(targetnames, {all = option.get("all")})) do
_package_target(target)
- else
- -- package default or all targets
- for _, target in ipairs(project.ordertargets()) do
- if target:is_default() or option.get("all") then
- _package_target(target)
- end
- end
end
-- unlock the whole project
diff --git a/xmake/actions/package/oldpkg/main.lua b/xmake/actions/package/oldpkg/main.lua
index 82d5d07f1..db9a5c0de 100644
--- a/xmake/actions/package/oldpkg/main.lua
+++ b/xmake/actions/package/oldpkg/main.lua
@@ -24,7 +24,7 @@ import("core.base.task")
import("core.project.rule")
import("core.project.config")
import("core.project.project")
-import("private.detect.check_targetname")
+import("private.action.utils", {alias = "action_utils"})
-- package library
function _package_library(target)
@@ -183,24 +183,19 @@ function main()
-- lock the whole project
project.lock()
- -- get the target name
- local targetname = option.get("target")
+ -- get the target names
+ local targetnames = option.get("targets")
-- build it first
- task.run("build", {target = targetname, all = option.get("all")})
+ task.run("build", {targets = targetnames, all = option.get("all")})
- -- package the given target?
- if targetname then
- local target = assert(check_targetname(targetname))
- _package_targets(target:orderdeps())
- _package_target(target)
- else
- -- package default or all targets
- for _, target in ipairs(project.ordertargets()) do
- if target:is_default() or option.get("all") then
- _package_target(target)
- end
+ -- package the given targets, also package the deps of the explicitly given targets
+ local explicit = targetnames and #targetnames > 0
+ for _, target in ipairs(action_utils.get_targets(targetnames, {all = option.get("all")})) do
+ if explicit then
+ _package_targets(target:orderdeps())
end
+ _package_target(target)
end
-- unlock the whole project
diff --git a/xmake/actions/package/remote/main.lua b/xmake/actions/package/remote/main.lua
index 45746eb69..dbb9f9fde 100644
--- a/xmake/actions/package/remote/main.lua
+++ b/xmake/actions/package/remote/main.lua
@@ -25,7 +25,7 @@ import("core.project.rule")
import("core.project.config")
import("core.project.project")
import("core.base.bit")
-import("private.detect.check_targetname")
+import("private.action.utils", {alias = "action_utils"})
-- get library deps
function _get_librarydeps(target)
@@ -151,18 +151,10 @@ function main()
-- load config
config.load()
- -- package the given target?
- local targetname = option.get("target")
- if targetname then
- local target = assert(check_targetname(targetname))
+ -- package the given targets
+ local targetnames = option.get("targets")
+ for _, target in ipairs(action_utils.get_targets(targetnames, {all = option.get("all")})) do
_package_target(target)
- else
- -- package default or all targets
- for _, target in ipairs(project.ordertargets()) do
- if target:is_default() or option.get("all") then
- _package_target(target)
- end
- end
end
-- unlock the whole project
diff --git a/xmake/actions/package/xmake.lua b/xmake/actions/package/xmake.lua
index 283edc815..d64a1e454 100644
--- a/xmake/actions/package/xmake.lua
+++ b/xmake/actions/package/xmake.lua
@@ -22,7 +22,7 @@ task("package")
set_category("action")
on_run("main")
set_menu {
- usage = "xmake package|p [options] [target]",
+ usage = "xmake package|p [options] [targets]",
description = "Package target.",
shortname = 'p',
options = {
@@ -37,7 +37,9 @@ task("package")
{nil, "version", "kv", nil, "Set the version of remote package."},
{nil, "shasum", "kv", nil, "Set the sha256 or commit of remote package."},
{},
- {nil, "target", "v", nil, "The target name. It will package all default targets if this parameter is not specified.",
+ {nil, "targets", "vs", nil, "The target names. It will package all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake package target1 target2 ...",
values = function (complete, opt)
return import("private.utils.complete_helper.targets")(complete, opt)
end }
diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua
index d9b5e83d3..f6baa4253 100644
--- a/xmake/actions/run/main.lua
+++ b/xmake/actions/run/main.lua
@@ -29,7 +29,7 @@ import("devel.debugger")
import("async.runjobs")
import("private.action.run.runenvs")
import("private.service.remote_build.action", {alias = "remote_build_action"})
-import("private.detect.check_targetname")
+import("private.detect.check_targetnames")
import("lib.detect.find_tool")
import("private.action.utils", {alias = "action_utils"})
@@ -232,7 +232,7 @@ function _check_targets(targetname, group_pattern)
-- get targets
local targets = {}
if targetname then
- local target = assert(check_targetname(targetname))
+ local target = assert(check_targetnames(targetname))
table.insert(targets, target)
else
for _, target in ipairs(project.ordertargets()) do
diff --git a/xmake/actions/uninstall/main.lua b/xmake/actions/uninstall/main.lua
index 4fb411892..e8ef87035 100644
--- a/xmake/actions/uninstall/main.lua
+++ b/xmake/actions/uninstall/main.lua
@@ -32,12 +32,12 @@ function main()
-- load config first
task.run("config", {require = false}, {disable_dump = true})
- -- attempt to uninstall directly, TODO group_pattern
- local targetname, group_pattern = action_utils.get_target_and_group()
+ -- attempt to uninstall directly
+ local targetnames, group_pattern = action_utils.get_targets_and_group()
try
{
function ()
- uninstall(targetname)
+ uninstall(targetnames, group_pattern)
cprint("${color.success}uninstall ok!")
end,
@@ -51,7 +51,7 @@ function main()
local ok = try
{
function ()
- uninstall(targetname)
+ uninstall(targetnames, group_pattern)
cprint("${color.success}uninstall ok!")
return true
end
@@ -70,7 +70,8 @@ function main()
-- uninstall target with administrator permission
sudo.execl(path.join(os.scriptdir(), "uninstall_admin.lua"), {
- targetname or "__all",
+ targetnames and table.concat(targetnames, path.envsep()) or "__all",
+ group_pattern or "",
option.get("installdir") or "",
option.get("bindir"),
option.get("libdir"),
diff --git a/xmake/actions/uninstall/uninstall.lua b/xmake/actions/uninstall/uninstall.lua
index 9a95da9dd..a5ac53cb9 100644
--- a/xmake/actions/uninstall/uninstall.lua
+++ b/xmake/actions/uninstall/uninstall.lua
@@ -23,6 +23,7 @@ import("core.base.task")
import("core.project.rule")
import("core.project.project")
import("target.action.uninstall", {alias = "_do_uninstall_target"})
+import("private.action.utils", {alias = "action_utils"})
-- on uninstall target
function _on_uninstall_target(target)
@@ -106,20 +107,12 @@ function _uninstall_targets(targets)
end
-- uninstall
-function main(targetname)
- local targets = {}
- if targetname and not targetname:startswith("__") then
- local target = project.target(targetname)
- table.insert(targets, target)
- else
- for _, target in ipairs(project.ordertargets()) do
- local group = target:get("group")
- if (target:is_default() and not group_pattern) or targetname == "__all" or (group_pattern and group and group:match(group_pattern)) then
- table.insert(targets, target)
- end
- end
- end
+--
+-- @param targetnames the target names (table), a single target name, or the magic "__all"/"__def"
+--
+function main(targetnames, group_pattern)
+ local targets = action_utils.get_targets(targetnames, {group_pattern = group_pattern})
if #targets > 0 then
- _uninstall_targets(table.unique(targets))
+ _uninstall_targets(targets)
end
end
diff --git a/xmake/actions/uninstall/uninstall_admin.lua b/xmake/actions/uninstall/uninstall_admin.lua
index b8d654c3d..ce036ec19 100644
--- a/xmake/actions/uninstall/uninstall_admin.lua
+++ b/xmake/actions/uninstall/uninstall_admin.lua
@@ -25,8 +25,16 @@ import("core.project.project")
import("core.platform.platform")
import("uninstall")
-function main(targetname, installdir, bindir, libdir, includedir)
+function main(targetname, group_pattern, installdir, bindir, libdir, includedir)
local verbose = option.get("verbose")
+
+ -- the targetname may be a list of target names joined with the path separator
+ if targetname and targetname:find(path.envsep(), 1, true) then
+ targetname = path.splitenv(targetname)
+ end
+ if group_pattern and #group_pattern == 0 then
+ group_pattern = nil
+ end
if installdir and #installdir == 0 then
installdir = nil
end
@@ -60,6 +68,6 @@ function main(targetname, installdir, bindir, libdir, includedir)
option.set("includedir", includedir)
end
-- uninstall target
- uninstall(targetname ~= "__all" and targetname or nil)
+ uninstall(targetname ~= "__all" and targetname or nil, group_pattern)
option.restore()
end
diff --git a/xmake/actions/uninstall/xmake.lua b/xmake/actions/uninstall/xmake.lua
index 72ba9c3f2..a31b7736b 100644
--- a/xmake/actions/uninstall/xmake.lua
+++ b/xmake/actions/uninstall/xmake.lua
@@ -22,7 +22,7 @@ task("uninstall")
set_category("action")
on_run("main")
set_menu {
- usage = "xmake uninstall|u [options] [target]",
+ usage = "xmake uninstall|u [options] [targets]",
description = "Uninstall the project binary files.",
shortname = 'u',
options = {
@@ -41,7 +41,9 @@ task("uninstall")
" xmake uninstall --group=benchmark/*" },
{nil, "admin", "k", nil , "Try to request administrator permission to uninstall"},
{ },
- {nil, "target", "v", nil , "The target name. It will uninstall all default targets if this parameter is not specified.",
+ {nil, "targets", "vs", nil , "The target names. It will uninstall all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake uninstall target1 target2 ...",
values = function (complete, opt)
return import("private.utils.complete_helper.targets")(complete, opt)
end}
diff --git a/xmake/modules/cli/amalgamate.lua b/xmake/modules/cli/amalgamate.lua
index b76f60b6e..293b0c445 100644
--- a/xmake/modules/cli/amalgamate.lua
+++ b/xmake/modules/cli/amalgamate.lua
@@ -24,7 +24,7 @@ import("core.base.graph")
import("core.project.config")
import("core.project.task")
import("core.project.project")
-import("private.detect.check_targetname")
+import("private.detect.check_targetnames")
-- the options
local options =
@@ -160,7 +160,7 @@ function main(...)
-- generate amalgamate code
args.outputdir = args.outputdir or config.builddir()
if args.target then
- local target = assert(check_targetname(args.target))
+ local target = assert(check_targetnames(args.target))
_generate_amalgamate_code(target, args)
else
for _, target in ipairs(project.ordertargets()) do
diff --git a/xmake/modules/private/action/utils.lua b/xmake/modules/private/action/utils.lua
index 9b83b59ab..5b83a522b 100644
--- a/xmake/modules/private/action/utils.lua
+++ b/xmake/modules/private/action/utils.lua
@@ -20,6 +20,8 @@
-- imports
import("core.base.option")
+import("core.project.project")
+import("private.detect.check_targetnames")
-- get target name and group pattern from option
function get_target_and_group()
@@ -32,3 +34,63 @@ function get_target_and_group()
end
return targetname, group_pattern
end
+
+-- get target names and group pattern from option
+--
+-- it supports building multiple targets, e.g. `xmake build target1 target2 ...`
+-- and is compatible with the legacy single `target` option passed programmatically.
+--
+function get_targets_and_group()
+ local targetnames
+ local group_pattern = option.get("group")
+ if group_pattern then
+ group_pattern = "^" .. path.pattern(group_pattern) .. "$"
+ else
+ targetnames = option.get("targets")
+ if not targetnames then
+ local targetname = option.get("target")
+ if targetname then
+ targetnames = {targetname}
+ end
+ end
+ if targetnames then
+ targetnames = table.wrap(targetnames)
+ end
+ end
+ return targetnames, group_pattern
+end
+
+-- get the selected target objects from the given target names
+--
+-- if explicit target names are given, the matching targets are returned (and checked).
+-- otherwise it selects the default/all/group targets, e.g. the actions like
+-- build/install/uninstall/package/format share the same selection rule.
+--
+-- @param targetnames a list of target names, a single target name, or the magic "__all"/"__def"
+-- @param opt the options, e.g. {group_pattern = ..., all = false}
+--
+-- @return the selected target objects (list)
+--
+function get_targets(targetnames, opt)
+ opt = opt or {}
+
+ -- select the explicitly given targets (table.wrap to always get a list back)
+ local targets
+ if type(targetnames) == "table" or (type(targetnames) == "string" and not targetnames:startswith("__")) then
+ targets = assert(check_targetnames(table.wrap(targetnames)))
+ else
+ -- otherwise select the default/all/group targets
+ targets = {}
+ local all = opt.all or targetnames == "__all" or option.get("all")
+ local group_pattern = opt.group_pattern
+ for _, target in ipairs(project.ordertargets()) do
+ local group = target:get("group")
+ if (target:is_default() and not group_pattern) or all or (group_pattern and group and group:match(group_pattern)) then
+ table.insert(targets, target)
+ end
+ end
+ end
+
+ -- remove duplicates, e.g. the same target name may be given more than once
+ return table.unique(targets)
+end
diff --git a/xmake/modules/private/detect/check_targetname.lua b/xmake/modules/private/detect/check_targetnames.lua
index 13a04c580..a4d3c3fc8 100644
--- a/xmake/modules/private/detect/check_targetname.lua
+++ b/xmake/modules/private/detect/check_targetnames.lua
@@ -14,30 +14,16 @@
--
-- Copyright (C) 2015-present, Xmake Open Source Community.
--
--- @author Shiffted
--- @file check_targetname.lua
+-- @author ruki
+-- @file check_targetnames.lua
--
-- imports
import("core.project.project")
import("private.detect.find_similar_targetnames")
--- check if a target name is valid
---
--- @param targetname the target name to check for
--- @param opt the argument options, e.g. {find_similar = false, max_similar = 5}
--- @return target or nil, errors
---
--- @code
---
--- local target, errors = check_targetname("mytarget")
--- local target, errors = check_targetname("mytarget", {find_similar = false})
---
--- @endcode
---
-function main(targetname, opt)
- opt = opt or {}
-
+-- check if a single target name is valid
+function _check_targetname(targetname, opt)
local target = project.target(targetname)
if target then
return target
@@ -54,3 +40,37 @@ function main(targetname, opt)
end
return nil, errors
end
+
+-- check if the given target names are valid
+--
+-- it accepts either a single target name or a list of target names. for a single
+-- target name (string), it returns the single matching target; for a list, it
+-- returns the matching targets as a list.
+--
+-- @param targetnames a single target name or a list of target names to check for
+-- @param opt the argument options, e.g. {find_similar = false, max_similar = 5}
+-- @return target(s) or nil, errors
+--
+-- @code
+--
+-- local target = assert(check_targetnames("mytarget"))
+-- local targets = assert(check_targetnames({"target1", "target2"}))
+--
+-- @endcode
+--
+function main(targetnames, opt)
+ opt = opt or {}
+ local targets = {}
+ for _, targetname in ipairs(table.wrap(targetnames)) do
+ local target, errors = _check_targetname(targetname, opt)
+ if not target then
+ return nil, errors
+ end
+ table.insert(targets, target)
+ end
+ -- unwrap to a single target if a single target name is given
+ if type(targetnames) ~= "table" then
+ return targets[1]
+ end
+ return targets
+end
diff --git a/xmake/plugins/format/main.lua b/xmake/plugins/format/main.lua
index 7d5e1de66..408de0421 100644
--- a/xmake/plugins/format/main.lua
+++ b/xmake/plugins/format/main.lua
@@ -93,22 +93,6 @@ function _get_file_patterns(sourcefiles)
return patterns
end
--- get all the targets that match the group or targetname
-function _get_targets(targetname, group_pattern)
- local targets = {}
- if targetname then
- table.insert(targets, project.target(targetname))
- else
- for _, target in pairs(project.targets()) do
- local group = target:get("group")
- if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then
- table.insert(targets, target)
- end
- end
- end
- return targets
-end
-
-- tell if the source batch is a c/c++/objc/objc++/cuda source batch
function _source_batch_should_format(sourcebatch)
local rulename = sourcebatch.rulename
@@ -178,8 +162,8 @@ function main()
-- collect sourcefiles
local sourcefiles = {}
- local targetname, group_pattern = action_utils.get_target_and_group()
- local targets = _get_targets(targetname, group_pattern)
+ local targetnames, group_pattern = action_utils.get_targets_and_group()
+ local targets = action_utils.get_targets(targetnames, {group_pattern = group_pattern})
if option.get("files") then
local filepatterns = _get_file_patterns(option.get("files"))
for _, target in ipairs(targets) do
diff --git a/xmake/plugins/format/xmake.lua b/xmake/plugins/format/xmake.lua
index d9e34572b..5de1b8120 100644
--- a/xmake/plugins/format/xmake.lua
+++ b/xmake/plugins/format/xmake.lua
@@ -45,7 +45,9 @@ task("format")
" - xmake format --files='src/**.c|excluded_file.c'",
" - xmake format --files='src/main.c" .. path.envsep() .. "src/test.c'" },
{},
- {nil, "target", "v", nil, "The target name. It will format all default targets if this parameter is not specified."
+ {nil, "targets", "vs", nil, "The target names. It will format all default targets if this parameter is not specified.",
+ "e.g.",
+ " xmake format target1 target2 ..."
, values = function (complete, opt) return import("private.utils.complete_helper.targets")(complete, opt) end }
}
}
diff --git a/xmake/plugins/show/info/depgraph.lua b/xmake/plugins/show/info/depgraph.lua
index 2c73f3abc..b8107a558 100644
--- a/xmake/plugins/show/info/depgraph.lua
+++ b/xmake/plugins/show/info/depgraph.lua
@@ -23,7 +23,7 @@ import("core.base.option")
import("core.base.json")
import("core.project.config")
import("core.project.project")
-import("private.detect.check_targetname")
+import("private.detect.check_targetnames")
function _collect_target_entry(target)
local deps = {}
@@ -135,7 +135,7 @@ function main(name)
local root_target
if name then
- root_target = assert(check_targetname(name))
+ root_target = assert(check_targetnames(name))
end
local graph = _collect_target_graph(root_target)
diff --git a/xmake/plugins/show/info/target.lua b/xmake/plugins/show/info/target.lua
index 75f31f9a5..099a0419d 100644
--- a/xmake/plugins/show/info/target.lua
+++ b/xmake/plugins/show/info/target.lua
@@ -24,7 +24,7 @@ import("core.base.json")
import("core.base.hashset")
import("core.project.config")
import("core.language.language")
-import("private.detect.check_targetname")
+import("private.detect.check_targetnames")
-- get source info data
function _get_sourceinfo(target, name, item, opt)
@@ -371,7 +371,7 @@ function main(name)
end
assert(name, "please specify the target name, e.g. xmake show --info=target --target=xxx")
- local target = assert(check_targetname(name))
+ local target = assert(check_targetnames(name))
local info = _collect_target_info(target)
if format == "json" then
diff --git a/xmake/rules/xcode/application/install.lua b/xmake/rules/xcode/application/install.lua
index 1f1578fe1..4d5053240 100644
--- a/xmake/rules/xcode/application/install.lua
+++ b/xmake/rules/xcode/application/install.lua
@@ -32,7 +32,7 @@ function _install_for_ios(target)
-- get *.ipa file
local ipafile = path.join(path.directory(appdir), path.basename(appdir) .. ".ipa")
if not os.isfile(ipafile) or os.mtime(target:targetfile()) > os.mtime(ipafile) then
- task.run("package", {target = target:name()})
+ task.run("package", {targets = {target:name()}})
end
assert(os.isfile(ipafile), "please run `xmake package` first!")