Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve to select script #4983

Merged
merged 3 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading