summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-02-15 00:04:49 +0800
committerGitHub <[email protected]>2024-02-15 00:04:49 +0800
commite860f98a8bbc60d296b03a95c374609be86713d8 (patch)
tree49a98ee83d94ea1be8f764cbb260f1f88a298f34
parent2dc22332518a885e565eb17e97f3bafe405748f4 (diff)
parentd069171eaf399228bac1b2e3c2f6c79f06399bbf (diff)
Merge pull request #4729 from xmake-io/script
Improve to select script
-rw-r--r--tests/apis/xxx_script/xmake.lua16
-rw-r--r--xmake/core/base/private/select_script.lua140
-rw-r--r--xmake/core/package/package.lua44
-rw-r--r--xmake/core/project/rule.lua44
-rw-r--r--xmake/core/project/target.lua44
-rw-r--r--xmake/core/sandbox/modules/import/private/core/base/select_script.lua23
-rw-r--r--xmake/plugins/pack/xpack.lua47
-rw-r--r--xmake/plugins/pack/xpack_component.lua47
8 files changed, 189 insertions, 216 deletions
diff --git a/tests/apis/xxx_script/xmake.lua b/tests/apis/xxx_script/xmake.lua
index c3acce0ab..9bfb456b0 100644
--- a/tests/apis/xxx_script/xmake.lua
+++ b/tests/apis/xxx_script/xmake.lua
@@ -1,7 +1,7 @@
target("test")
before_build("iphoneos|arm64", "macosx", function (target)
- assert(is_plat("macosx") or (is_plat("iphoneos") and is_arch("arm64")))
+ assert(target:is_plat("macosx") or (target:is_plat("iphoneos") and target:is_arch("arm64")))
end)
before_build(function (target)
@@ -16,6 +16,18 @@ target("test")
print("after_build")
end)
+ after_build("!macosx", function (target)
+ print("after_build !macosx")
+ end)
+
+ after_build("!linux", function (target)
+ print("after_build !linux")
+ end)
+
+ after_build("!iphoneos", function (target)
+ print("after_build !iphoneos")
+ end)
+
after_build("linux|*", function (target)
- assert(is_plat("linux"))
+ assert(target:is_plat("linux"))
end)
diff --git a/xmake/core/base/private/select_script.lua b/xmake/core/base/private/select_script.lua
new file mode 100644
index 000000000..cac17251f
--- /dev/null
+++ b/xmake/core/base/private/select_script.lua
@@ -0,0 +1,140 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file select_script.lua
+--
+
+-- load modules
+local table = require("base/table")
+local utils = require("base/utils")
+
+-- match pattern, matched mode: plat|arch, excluded mode: !plat|arch
+function _match_pattern(pattern, plat, arch, excluded)
+ local is_excluded_pattern = pattern:find('!', 1, true)
+ if excluded and is_excluded_pattern then
+ return not ('!' .. plat .. '|' .. arch):match('^' .. pattern .. '$') and
+ not (plat .. '|!' .. arch):match('^' .. pattern .. '$') and
+ not ('!' .. plat):match('^' .. pattern .. '$')
+ elseif not is_excluded_pattern then
+ return (plat .. '|' .. arch):match('^' .. pattern .. '$') or plat:match('^' .. pattern .. '$')
+ end
+end
+
+-- match patterns
+function _match_patterns(patterns, plat, arch, excluded)
+ for _, pattern in ipairs(patterns) do
+ if _match_pattern(pattern, plat, arch, excluded) then
+ return true
+ end
+ end
+end
+
+-- mattch the script pattern
+--
+-- @note interpreter has converted pattern to a lua pattern ('*' => '.*')
+--
+-- matched pattern:
+-- plat|arch@subhost|subarch
+--
+-- e.g.
+--
+-- `@linux`
+-- `@linux|x86_64`
+-- `@macosx,linux`
+-- `android@macosx,linux`
+-- `android|armeabi-v7a@macosx,linux`
+-- `android|armeabi-v7a,iphoneos@macosx,linux|x86_64`
+-- `android|armeabi-v7a@linux|x86_64`
+-- `linux|*`
+--
+-- excluded pattern:
+-- !plat|!arch@!subhost|!subarch
+--
+-- e.g.
+--
+-- `@!linux`
+-- `@!linux|x86_64`
+-- `@!macosx,!linux`
+-- `!android@macosx,!linux`
+-- `android|!armeabi-v7a@macosx,!linux`
+-- `android|armeabi-v7a,!iphoneos@macosx,!linux|x86_64`
+-- `!android|armeabi-v7a@!linux|!x86_64`
+-- `!linux|*`
+--
+function _match_script(pattern, plat, arch, excluded)
+ local splitinfo = pattern:split("@", {plain = true})
+ local plat_part = splitinfo[1]
+ local host_part = splitinfo[2]
+ local plat_patterns = plat_part:split(",", {plain = true})
+ local host_patterns
+ if host_part then
+ host_patterns = host_part:split(",", {plain = true})
+ end
+ if _match_patterns(plat_patterns, plat, arch, excluded) then
+ if host_patterns and #host_patterns > 0 and
+ not _match_patterns(host_patterns, os.subhost(), os.subarch(), excluded) then
+ return false
+ end
+ return true
+ end
+end
+
+-- select the matched pattern script for the current platform/architecture
+function select_script(scripts, opt)
+ opt = opt or {}
+ local result = nil
+ if type(scripts) == "function" then
+ result = scripts
+ elseif type(scripts) == "table" then
+ local plat = opt.plat or ""
+ local arch = opt.arch or ""
+ local script_matched
+ for pattern, script in pairs(scripts) do
+ if not pattern:startswith("__") and _match_script(pattern, plat, arch) then
+ script_matched = script
+ break
+ end
+ end
+ if not script_matched then
+ local scripts_fallback = {}
+ local patterns_fallback = {}
+ for pattern, script in pairs(scripts) do
+ if not pattern:startswith("__") and _match_script(pattern, plat, arch, true) then
+ table.insert(scripts_fallback, script)
+ table.insert(patterns_fallback, pattern)
+ end
+ end
+ script_matched = scripts_fallback[1]
+ if script_matched and #scripts_fallback > 0 then
+ local conflict_patterns = {patterns_fallback[1]}
+ for idx, script in ipairs(scripts_fallback) do
+ local pattern = patterns_fallback[idx]
+ if script ~= script_matched then
+ table.insert(conflict_patterns, pattern)
+ end
+ end
+ if #conflict_patterns > 1 then
+ utils.warning("multiple script patterns are matched, %s", table.concat(conflict_patterns, ", "))
+ end
+ end
+ end
+ result = script_matched or scripts["__generic__"]
+ end
+ return result
+end
+
+return select_script
diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua
index d151a9317..a3985a5e9 100644
--- a/xmake/core/package/package.lua
+++ b/xmake/core/package/package.lua
@@ -34,6 +34,7 @@ local option = require("base/option")
local hashset = require("base/hashset")
local scopeinfo = require("base/scopeinfo")
local interpreter = require("base/interpreter")
+local select_script = require("base/private/select_script")
local memcache = require("cache/memcache")
local toolchain = require("tool/toolchain")
local compiler = require("tool/compiler")
@@ -1662,48 +1663,7 @@ function _instance:script(name, generic)
-- get script
local script = self:get(name)
- local result = nil
- if type(script) == "function" then
- result = script
- elseif type(script) == "table" then
-
- -- get plat and arch
- local plat = self:plat() or ""
- local arch = self:arch() or ""
-
- -- match pattern
- --
- -- `@linux`
- -- `@linux|x86_64`
- -- `@macosx,linux`
- -- `android@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux|x86_64`
- -- `android|armeabi-v7a@linux|x86_64`
- --
- for _pattern, _script in pairs(script) do
- local hosts = {}
- local hosts_spec = false
- _pattern = _pattern:gsub("@(.+)", function (v)
- for _, host in ipairs(v:split(',')) do
- hosts[host] = true
- hosts_spec = true
- end
- return ""
- end)
- if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()])
- and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then
- result = _script
- break
- end
- end
-
- -- get generic script
- result = result or script["__generic__"] or generic
- end
-
- -- only generic script
- result = result or generic
+ local result = select_script(script, {plat = self:plat(), arch = self:arch()}) or generic
-- imports some modules first
if result and result ~= generic then
diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua
index c6f476d61..8bf4e1b39 100644
--- a/xmake/core/project/rule.lua
+++ b/xmake/core/project/rule.lua
@@ -30,6 +30,7 @@ local table = require("base/table")
local global = require("base/global")
local interpreter = require("base/interpreter")
local instance_deps = require("base/private/instance_deps")
+local select_script = require("base/private/select_script")
local config = require("project/config")
local sandbox = require("sandbox/sandbox")
local sandbox_os = require("sandbox/modules/os")
@@ -147,48 +148,7 @@ function _instance:script(name, generic)
-- get script
local script = self:get(name)
- local result = nil
- if type(script) == "function" then
- result = script
- elseif type(script) == "table" then
-
- -- get plat and arch
- local plat = config.get("plat") or ""
- local arch = config.get("arch") or ""
-
- -- match pattern
- --
- -- `@linux`
- -- `@linux|x86_64`
- -- `@macosx,linux`
- -- `android@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux|x86_64`
- -- `android|armeabi-v7a@linux|x86_64`
- --
- for _pattern, _script in pairs(script) do
- local hosts = {}
- local hosts_spec = false
- _pattern = _pattern:gsub("@(.+)", function (v)
- for _, host in ipairs(v:split(',')) do
- hosts[host] = true
- hosts_spec = true
- end
- return ""
- end)
- if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()])
- and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then
- result = _script
- break
- end
- end
-
- -- get generic script
- result = result or script["__generic__"] or generic
- end
-
- -- only generic script
- result = result or generic
+ local result = select_script(script, {plat = config.get("plat"), arch = config.get("arch")}) or generic
-- imports some modules first
if result and result ~= generic then
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index 25685ccb5..39d43bec9 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -32,6 +32,7 @@ local table = require("base/table")
local baseoption = require("base/option")
local hashset = require("base/hashset")
local deprecated = require("base/deprecated")
+local select_script = require("base/private/select_script")
local instance_deps = require("base/private/instance_deps")
local memcache = require("cache/memcache")
local rule = require("project/rule")
@@ -2341,48 +2342,7 @@ function _instance:script(name, generic)
-- get script
local script = self:get(name)
- local result = nil
- if type(script) == "function" then
- result = script
- elseif type(script) == "table" then
-
- -- get plat and arch
- local plat = self:plat()
- local arch = self:arch()
-
- -- match pattern
- --
- -- `@linux`
- -- `@linux|x86_64`
- -- `@macosx,linux`
- -- `android@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux|x86_64`
- -- `android|armeabi-v7a@linux|x86_64`
- --
- for _pattern, _script in pairs(script) do
- local hosts = {}
- local hosts_spec = false
- _pattern = _pattern:gsub("@(.+)", function (v)
- for _, host in ipairs(v:split(',')) do
- hosts[host] = true
- hosts_spec = true
- end
- return ""
- end)
- if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()])
- and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then
- result = _script
- break
- end
- end
-
- -- get generic script
- result = result or script["__generic__"] or generic
- end
-
- -- only generic script
- result = result or generic
+ local result = select_script(script, {plat = self:plat(), arch = self:arch()}) or generic
-- imports some modules first
if result and result ~= generic then
diff --git a/xmake/core/sandbox/modules/import/private/core/base/select_script.lua b/xmake/core/sandbox/modules/import/private/core/base/select_script.lua
new file mode 100644
index 000000000..9cb2307af
--- /dev/null
+++ b/xmake/core/sandbox/modules/import/private/core/base/select_script.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file select_script.lua
+--
+
+return require("base/private/select_script")
+
+
diff --git a/xmake/plugins/pack/xpack.lua b/xmake/plugins/pack/xpack.lua
index 0eae84a7a..1868252d7 100644
--- a/xmake/plugins/pack/xpack.lua
+++ b/xmake/plugins/pack/xpack.lua
@@ -25,6 +25,7 @@ import("core.base.semver")
import("core.base.hashset")
import("core.project.config")
import("core.project.project")
+import("private.core.base.select_script")
import("lib.detect.find_tool")
import("filter")
import("xpack_component")
@@ -116,51 +117,9 @@ end
-- get xxx_script
function xpack:script(name, generic)
-
- -- get script
local script = self:get(name)
- local result = nil
- if type(script) == "function" then
- result = script
- elseif type(script) == "table" then
-
- -- get plat and arch
- local plat = self:plat()
- local arch = self:arch()
-
- -- match pattern
- --
- -- `@linux`
- -- `@linux|x86_64`
- -- `@macosx,linux`
- -- `android@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux|x86_64`
- -- `android|armeabi-v7a@linux|x86_64`
- --
- for _pattern, _script in pairs(script) do
- local hosts = {}
- local hosts_spec = false
- _pattern = _pattern:gsub("@(.+)", function (v)
- for _, host in ipairs(v:split(',')) do
- hosts[host] = true
- hosts_spec = true
- end
- return ""
- end)
- if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()])
- and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then
- result = _script
- break
- end
- end
-
- -- get generic script
- result = result or script["__generic__"] or generic
- end
-
- -- only generic script
- return result or generic
+ local result = select_script(script, {plat = self:plat(), arch = self:arch()}) or generic
+ return result
end
-- get targets
diff --git a/xmake/plugins/pack/xpack_component.lua b/xmake/plugins/pack/xpack_component.lua
index dd2c36069..14e19efd5 100644
--- a/xmake/plugins/pack/xpack_component.lua
+++ b/xmake/plugins/pack/xpack_component.lua
@@ -23,6 +23,7 @@ import("core.base.object")
import("core.base.option")
import("core.project.config")
import("core.project.project")
+import("private.core.base.select_script")
-- define module
local xpack_component = xpack_component or object {_init = {"_name", "_info", "_package"}}
@@ -72,51 +73,9 @@ end
-- get xxx_script
function xpack_component:script(name, generic)
-
- -- get script
local script = self:get(name)
- local result = nil
- if type(script) == "function" then
- result = script
- elseif type(script) == "table" then
-
- -- get plat and arch
- local plat = self:plat()
- local arch = self:arch()
-
- -- match pattern
- --
- -- `@linux`
- -- `@linux|x86_64`
- -- `@macosx,linux`
- -- `android@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux`
- -- `android|armeabi-v7a@macosx,linux|x86_64`
- -- `android|armeabi-v7a@linux|x86_64`
- --
- for _pattern, _script in pairs(script) do
- local hosts = {}
- local hosts_spec = false
- _pattern = _pattern:gsub("@(.+)", function (v)
- for _, host in ipairs(v:split(',')) do
- hosts[host] = true
- hosts_spec = true
- end
- return ""
- end)
- if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()])
- and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then
- result = _script
- break
- end
- end
-
- -- get generic script
- result = result or script["__generic__"] or generic
- end
-
- -- only generic script
- return result or generic
+ local result = select_script(script, {plat = self:plat(), arch = self:arch()}) or generic
+ return result
end
-- get targets