summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-04-17 22:50:06 +0800
committerruki <[email protected]>2024-04-17 22:50:06 +0800
commit2190b08db954738da36feeb820e8771383caa5e0 (patch)
treed0a1fd3d98c6c21dfbe2acdf0c5be1f46788d54f
parente39ff9d876e33cc36e4eb9e196ca665ecefc9f96 (diff)
support logical expr for selecting script
-rw-r--r--tests/modules/private/select_script/test.lua11
-rw-r--r--xmake/core/base/interpreter.lua2
-rw-r--r--xmake/core/base/private/select_script.lua39
3 files changed, 47 insertions, 5 deletions
diff --git a/tests/modules/private/select_script/test.lua b/tests/modules/private/select_script/test.lua
index 90258c232..50ff3acee 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
@@ -28,6 +28,8 @@ function test_plat_only(t)
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"}))
@@ -119,3 +121,10 @@ 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("!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"}))
+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..243e41a60 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)
@@ -124,7 +125,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 +157,38 @@ function _match_script(pattern, opt)
end
end
+-- match the script expression pattern
+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 {}