diff options
| author | ruki <[email protected]> | 2024-02-15 00:04:49 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-15 00:04:49 +0800 |
| commit | e860f98a8bbc60d296b03a95c374609be86713d8 (patch) | |
| tree | 49a98ee83d94ea1be8f764cbb260f1f88a298f34 | |
| parent | 2dc22332518a885e565eb17e97f3bafe405748f4 (diff) | |
| parent | d069171eaf399228bac1b2e3c2f6c79f06399bbf (diff) | |
Merge pull request #4729 from xmake-io/script
Improve to select script
| -rw-r--r-- | tests/apis/xxx_script/xmake.lua | 16 | ||||
| -rw-r--r-- | xmake/core/base/private/select_script.lua | 140 | ||||
| -rw-r--r-- | xmake/core/package/package.lua | 44 | ||||
| -rw-r--r-- | xmake/core/project/rule.lua | 44 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 44 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/private/core/base/select_script.lua | 23 | ||||
| -rw-r--r-- | xmake/plugins/pack/xpack.lua | 47 | ||||
| -rw-r--r-- | xmake/plugins/pack/xpack_component.lua | 47 |
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 |
