summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-04-17 12:14:11 +0800
committerGitHub <[email protected]>2024-04-17 12:14:11 +0800
commite23083fd20b7223131f01e81e1d1646fdb18ac71 (patch)
treed6d0739aaf61eedbc0dd4959927fd01d94d0b336
parente39ff9d876e33cc36e4eb9e196ca665ecefc9f96 (diff)
parent2346d257b7d3a8d9be845eeea7763113647611df (diff)
Merge pull request #4983 from xmake-io/select
Improve to select script
-rw-r--r--tests/modules/private/select_script/test.lua28
-rw-r--r--xmake/core/base/interpreter.lua2
-rw-r--r--xmake/core/base/private/select_script.lua64
3 files changed, 64 insertions, 30 deletions
diff --git a/tests/modules/private/select_script/test.lua b/tests/modules/private/select_script/test.lua
index 90258c232..ff9b25e59 100644
--- a/tests/modules/private/select_script/test.lua
+++ b/tests/modules/private/select_script/test.lua
@@ -3,7 +3,7 @@ import("private.core.base.select_script")
function _match_patterns(patterns, opt)
local scripts = {}
for _, pattern in ipairs(patterns) do
- pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
+ pattern = pattern:gsub("([%+%.%-%^%$%%])", "%%%1")
pattern = pattern:gsub("%*", "\001")
pattern = pattern:gsub("\001", ".*")
scripts[pattern] = true
@@ -22,12 +22,12 @@ function test_plat_only(t)
t:require_not(_match_patterns("!mac*", {plat = "macosx"}))
t:require(_match_patterns("!macosx", {plat = "linux"}))
t:require(_match_patterns("!macosx,!android", {plat = "linux"}))
- t:require_not(_match_patterns("!macosx,!android", {plat = "android"}))
- t:require_not(_match_patterns("!macosx,!android", {plat = "macosx"}))
t:require(_match_patterns("!mac*", {plat = "linux"}))
end
function test_plat_arch(t)
+ t:require(_match_patterns("!wasm|!arm*", {plat = "linux", arch = "x86_64"}))
+ t:require_not(_match_patterns("!wasm|!arm*", {plat = "linux", arch = "arm64"}))
t:require(_match_patterns("*|x86_64", {plat = "macosx", arch = "x86_64"}))
t:require(_match_patterns("macosx|x86_64", {plat = "macosx", arch = "x86_64"}))
t:require(_match_patterns("macosx|x86_64,linux|x86_64", {plat = "macosx", arch = "x86_64"}))
@@ -37,8 +37,6 @@ function test_plat_arch(t)
t:require_not(_match_patterns("!macosx|x86_64", {plat = "macosx", arch = "x86_64"}))
t:require_not(_match_patterns("!mac*|x86_64", {plat = "macosx", arch = "x86_64"}))
t:require(_match_patterns("!macosx|x86_64", {plat = "linux", arch = "x86_64"}))
- t:require(_match_patterns("!macosx|x86_64,!iphoneos|arm64", {plat = "linux", arch = "x86_64"}))
- t:require_not(_match_patterns("!macosx|x86_64,!linux|x86_64", {plat = "linux", arch = "x86_64"}))
t:require(_match_patterns("!mac*|x86_64", {plat = "linux", arch = "x86_64"}))
t:require(_match_patterns("macosx|!i386", {plat = "macosx", arch = "x86_64"}))
t:require(_match_patterns("!macosx|!i386", {plat = "linux", arch = "x86_64"}))
@@ -53,7 +51,6 @@ end
function test_subhost_only(t)
t:require(_match_patterns("@*", {subhost = "macosx"}))
t:require(_match_patterns("@macosx", {subhost = "macosx"}))
- t:require(_match_patterns("@macosx,@linux", {subhost = "macosx"}))
t:require(_match_patterns("@mac*", {subhost = "macosx"}))
t:require_not(_match_patterns("@macosx", {subhost = "linux"}))
t:require_not(_match_patterns("@linux", {subhost = "macosx"}))
@@ -66,7 +63,6 @@ end
function test_subhost_subarch(t)
t:require(_match_patterns("@*|x86_64", {subhost = "macosx", subarch = "x86_64"}))
t:require(_match_patterns("@macosx|x86_64", {subhost = "macosx", subarch = "x86_64"}))
- t:require(_match_patterns("@macosx|x86_64,@linux|x86_64", {subhost = "macosx", subarch = "x86_64"}))
t:require(_match_patterns("@macosx|x86_*", {subhost = "macosx", subarch = "x86_64"}))
t:require_not(_match_patterns("@macosx|x86_64", {subhost = "linux", subarch = "x86_64"}))
t:require_not(_match_patterns("@macosx|i386", {subhost = "macosx", subarch = "x86_64"}))
@@ -87,7 +83,6 @@ end
function test_plat_subhost(t)
t:require(_match_patterns("*@macosx", {plat = "macosx", subhost = "macosx"}))
t:require(_match_patterns("android@macosx", {plat = "android", subhost = "macosx"}))
- t:require_not(_match_patterns("!android@macosx,!android@linux", {plat = "android", subhost = "macosx"}))
t:require(_match_patterns("android@macosx,linux", {plat = "android", subhost = "linux"}))
t:require(_match_patterns("android@mac*", {plat = "android", subhost = "macosx"}))
t:require(_match_patterns("android@!macosx", {plat = "android", subhost = "linux"}))
@@ -119,3 +114,20 @@ function test_plat_arch_subhost_subarch(t)
t:require_not(_match_patterns("iphon*|arm64@macosx|x86_64", {plat = "iphoneos", subhost = "linux", arch = "arm64", subarch = "x86_64"}))
t:require(_match_patterns("android|native@macosx|x86_64", {plat = "android", subhost = "macosx", arch = "x86_64", subarch = "x86_64"}))
end
+
+function test_logical_expr(t)
+ t:require(_match_patterns("!macosx|x86_64,!iphoneos|arm64", {plat = "linux", arch = "x86_64"}))
+ t:require(_match_patterns("!wasm|!arm* and !cross|!arm*", {plat = "linux", arch = "x86_64"}))
+ t:require_not(_match_patterns("!wasm|!arm* and !cross|!arm*", {plat = "linux", arch = "arm64"}))
+ t:require_not(_match_patterns("!wasm|!arm* and !cross|!arm*", {plat = "wasm", arch = "x86_64"}))
+ t:require(_match_patterns("!macosx|x86_64 or !iphoneos|arm64", {plat = "linux", arch = "x86_64"}))
+ t:require_not(_match_patterns("!android@macosx or !android@linux", {plat = "android", subhost = "macosx"}))
+ t:require(_match_patterns("@macosx|x86_64 or @linux|x86_64", {subhost = "macosx", subarch = "x86_64"}))
+ t:require(_match_patterns("@macosx or @linux", {subhost = "macosx"}))
+ t:require(_match_patterns("!wasm|!arm* or (!cross|!arm* or linux)", {plat = "linux", arch = "arm64"}))
+ t:require_not(_match_patterns("!wasm|!arm* or (!cross|!arm* and !linux)", {plat = "linux", arch = "arm64"}))
+ t:require_not(_match_patterns("!macosx|x86_64 and !linux|x86_64", {plat = "linux", arch = "x86_64"}))
+ t:require_not(_match_patterns("!macosx and !android", {plat = "android"}))
+ t:require_not(_match_patterns("!macosx and !android", {plat = "macosx"}))
+end
+
diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua
index e1cd08a78..1c85d870e 100644
--- a/xmake/core/base/interpreter.lua
+++ b/xmake/core/base/interpreter.lua
@@ -323,7 +323,7 @@ function interpreter:_api_register_xxx_script(scope_kind, action, ...)
assert(type(pattern) == "string")
-- convert pattern to a lua pattern ('*' => '.*')
- pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
+ pattern = pattern:gsub("([%+%.%-%^%$%%])", "%%%1")
pattern = pattern:gsub("%*", "\001")
pattern = pattern:gsub("\001", ".*")
diff --git a/xmake/core/base/private/select_script.lua b/xmake/core/base/private/select_script.lua
index 23c8b55b6..619a5eef2 100644
--- a/xmake/core/base/private/select_script.lua
+++ b/xmake/core/base/private/select_script.lua
@@ -19,8 +19,9 @@
--
-- load modules
-local table = require("base/table")
-local utils = require("base/utils")
+local table = require("base/table")
+local utils = require("base/utils")
+local hashset = require("base/hashset")
-- match pattern, matched mode: plat|arch, excluded mode: !plat|arch
function _match_pattern(pattern, plat, arch, opt)
@@ -36,9 +37,6 @@ function _match_pattern(pattern, plat, arch, opt)
local is_excluded_pattern = pattern_plat:find('!', 1, true)
if excluded and is_excluded_pattern then
matched = not ('!' .. plat):match('^' .. pattern_plat .. '$')
- if matched then
- return true
- end
elseif not is_excluded_pattern then
matched = plat:match('^' .. pattern_plat .. '$')
end
@@ -71,25 +69,11 @@ end
-- match patterns
function _match_patterns(patterns, plat, arch, opt)
- local patterns_excluded = {}
for _, pattern in ipairs(patterns) do
- if pattern:startswith("!") then
- table.insert(patterns_excluded, pattern)
- else
- if _match_pattern(pattern, plat, arch, opt) then
- return true
- end
- end
- end
- local matched = 0
- for _, pattern in ipairs(patterns_excluded) do
if _match_pattern(pattern, plat, arch, opt) then
- matched = matched + 1
+ return true
end
end
- if #patterns_excluded > 0 and #patterns_excluded == matched then
- return true
- end
end
-- mattch the script pattern
@@ -124,7 +108,7 @@ end
-- `!android|armeabi-v7a@!linux|!x86_64`
-- `!linux|*`
--
-function _match_script(pattern, opt)
+function _match_script_pattern(pattern, opt)
opt = opt or {}
local splitinfo = pattern:split("@", {strict = true, plain = true})
local plat_part = splitinfo[1]
@@ -156,6 +140,44 @@ function _match_script(pattern, opt)
end
end
+-- match the script expression pattern
+--
+-- e.g.
+-- !wasm|!arm* and !cross|!arm*
+-- wasm|!arm* or cross
+-- (!macosx and !iphoneos) or (!linux|!arm* and !cross|!arm*)
+--
+function _match_script(pattern, opt)
+ local idx = 0
+ local funcs = {}
+ local keywords = hashset.of("and", "or")
+ local has_logical_op = false
+ local pattern_expr = pattern:gsub("[^%(%)%s]+", function (w)
+ if keywords:has(w) then
+ has_logical_op = true
+ return
+ end
+ local name = "func_" .. idx
+ local func = function ()
+ return _match_script_pattern(w, opt)
+ end
+ funcs[name] = func
+ idx = idx + 1
+ return name .. "()"
+ end)
+ if has_logical_op then
+ local script = assert(load("return (" .. pattern_expr .. ")"), "invalid pattern: " .. pattern)
+ setfenv(script, funcs)
+ local ok, results = utils.trycall(script)
+ if not ok then
+ os.raise("invalid pattern: %s, error: %s", pattern, results or "unknown")
+ end
+ return results
+ else
+ return _match_script_pattern(pattern, opt)
+ end
+end
+
-- select the matched pattern script for the current platform/architecture
function select_script(scripts, opt)
opt = opt or {}