Skip to content

Commit

Permalink
Merge pull request #4983 from xmake-io/select
Browse files Browse the repository at this point in the history
Improve to select script
  • Loading branch information
waruqi authored Apr 17, 2024
2 parents e39ff9d + 2346d25 commit e23083f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 30 deletions.
28 changes: 20 additions & 8 deletions tests/modules/private/select_script/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"}))
Expand All @@ -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"}))
Expand All @@ -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"}))
Expand All @@ -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"}))
Expand All @@ -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"}))
Expand Down Expand Up @@ -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

2 changes: 1 addition & 1 deletion xmake/core/base/interpreter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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", ".*")

Expand Down
64 changes: 43 additions & 21 deletions xmake/core/base/private/select_script.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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 {}
Expand Down

0 comments on commit e23083f

Please sign in to comment.