From fb41663cb744304ea86af2149059141055d4e15d Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 5 Jan 2026 23:51:29 +0800 Subject: add package scheme --- xmake/core/package/package.lua | 1 + xmake/core/package/scheme.lua | 174 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 xmake/core/package/scheme.lua diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index ecffbc88f..63ef06c9f 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2894,6 +2894,7 @@ function package.apis() , "package.set_cachedir" , "package.set_installdir" , "package.add_bindirs" + , "package.add_installschemes" -- package.add_xxx , "package.add_deps" , "package.add_urls" diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua new file mode 100644 index 000000000..5932f22a6 --- /dev/null +++ b/xmake/core/package/scheme.lua @@ -0,0 +1,174 @@ +--!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, Xmake Open Source Community. +-- +-- @author ruki +-- @file scheme.lua +-- + +-- @ref https://github.com/xmake-io/xmake/issues/7184 +-- @note This module provides scheme management for packages, +-- allowing custom download schemes and configurations +-- to be defined and applied to package management. + +-- define module +local scheme = scheme or {} +local _instance = _instance or {} + +-- load modules +local os = require("base/os") +local io = require("base/io") +local path = require("base/path") +local utils = require("base/utils") +local table = require("base/table") +local option = require("base/option") +local hashset = require("base/hashset") +local scopeinfo = require("base/scopeinfo") +local interpreter = require("base/interpreter") +local language = require("language/language") +local sandbox = require("sandbox/sandbox") + +-- new an instance +function _instance.new(name, opt) + opt = opt or {} + local instance = table.inherit(_instance) + instance._NAME = name + instance._INFO = scopeinfo.new("scheme", {}, {interpreter = scheme._interpreter()}) + instance._PACKAGE = opt.package + return instance +end + +-- get the scheme name +function _instance:name() + return self._NAME +end + +-- get the type: scheme +function _instance:type() + return "scheme" +end + +-- get the it's package +function _instance:package() + return self._PACKAGE +end + +-- get the scheme configuration +function _instance:get(name) + return self._INFO:get(name) +end + +-- set the value to scheme info +function _instance:set(name, ...) + self._INFO:apival_set(name, ...) +end + +-- add the value to scheme info +function _instance:add(name, ...) + self._INFO:apival_add(name, ...) +end + +-- get the extra configuration +function _instance:extraconf(name, item, key) + local conf = self._INFO:extraconf(name, item, key) + if conf == nil and self:base() then + conf = self:base():extraconf(name, item, key) + end + return conf +end + +-- set the extra configuration +function _instance:extraconf_set(name, item, key, value) + return self._INFO:extraconf_set(name, item, key, value) +end + +-- get on_scheme script +function _instance:_on_scheme() + local script = self:package():get("scheme") + local result = nil + if type(script) == "function" then + result = script + elseif type(script) == "table" then + result = script[self:name()] + result = result or script["__generic__"] + end + return result +end + +-- load this scheme +function _instance:_load() + local loaded = self._LOADED + if not loaded then + local script = self:_on_scheme() + if script then + local ok, errors = sandbox.load(script, self:package(), self) + if not ok then + os.raise("load scheme(%s) failed, %s", self:name(), errors or "unknown errors") + end + end + self._LOADED = true + end +end + +-- interpreter +function scheme._interpreter() + local interp = scheme._INTERPRETER + if not interp then + interp = interpreter.new() + interp:api_define(scheme.apis()) + scheme._INTERPRETER = interp + end + return interp +end + +-- get scheme apis +function scheme.apis() + return { + values = { + -- scheme.set_xxx + "scheme.set_urls", + "scheme.set_policy", + -- scheme.add_xxx + "scheme.add_urls", + "scheme.add_patches", + "scheme.add_resources", + "scheme.add_versionfiles", + "scheme.add_versions" + }, + keyvalues = { + -- scheme.set_xxx + "scheme.set_policy" + -- scheme.add_xxx + , "scheme.add_patches" + , "scheme.add_resources" + }, + paths = { + -- scheme.add_xxx + "scheme.add_versionfiles" + }, + dictionary = { + -- scheme.add_xxx + "scheme.add_versions" + } + } +end + +-- new scheme +function scheme.new(name, opt) + return _instance.new(name, opt) +end + +-- return module +return scheme -- cgit v1.3.1 From 4255491d58e9a1ea99520f9b04640c6eabd6e84f Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 5 Jan 2026 23:53:30 +0800 Subject: add package schemes --- xmake/core/package/package.lua | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 63ef06c9f..36bb034d8 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -46,6 +46,7 @@ local policy = require("project/policy") local platform = require("platform/platform") local platform_menu = require("platform/menu") local component = require("package/component") +local scheme = require("package/scheme") local language = require("language/language") local language_menu = require("language/menu") local sandbox = require("sandbox/sandbox") @@ -2423,6 +2424,40 @@ function _instance:_sort_componentdeps(name) return orderdeps end +-- get the given package scheme +function _instance:scheme(name) + return self:schemes()[name] +end + +-- get package schemes +-- +-- .e.g. add_schemes("binary", "source") +-- +function _instance:schemes() + local schemes = self._SCHEMES + if not schemes then + schemes = {} + for _, name in ipairs(table.wrap(self:get("schemes"))) do + schemes[name] = scheme.new(name, {package = self}) + end + self._SCHEMES = schemes + end + return schemes +end + +-- get package schemes list (ordered) +function _instance:schemes_orderlist() + local schemes_orderlist = self._SCHEMES_ORDERLIST + if not schemes_orderlist then + schemes_orderlist = {} + for _, name in ipairs(table.wrap(self:get("schemes"))) do + table.insert(schemes_orderlist, self:scheme(name)) + end + self._SCHEMES_ORDERLIST = schemes_orderlist + end + return schemes_orderlist +end + -- generate lto configs function _instance:_generate_lto_configs(sourcekind) @@ -2894,7 +2929,7 @@ function package.apis() , "package.set_cachedir" , "package.set_installdir" , "package.add_bindirs" - , "package.add_installschemes" + , "package.add_schemes" -- package.add_xxx , "package.add_deps" , "package.add_urls" -- cgit v1.3.1 From 7d506590468cc2fc0984a9890b4cefead1a37718 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 5 Jan 2026 23:55:13 +0800 Subject: improve scheme --- xmake/core/package/component.lua | 4 ++-- xmake/core/package/package.lua | 4 ++++ xmake/core/package/scheme.lua | 10 +++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/xmake/core/package/component.lua b/xmake/core/package/component.lua index cfe0a9901..d93a4f7fb 100644 --- a/xmake/core/package/component.lua +++ b/xmake/core/package/component.lua @@ -78,8 +78,8 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) local conf = self._INFO:extraconf(name, item, key) - if conf == nil and self:base() then - conf = self:base():extraconf(name, item, key) + if conf == nil then + conf = self:package():extraconf(name, item, key) end return conf end diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 36bb034d8..b6c444778 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2440,6 +2440,10 @@ function _instance:schemes() for _, name in ipairs(table.wrap(self:get("schemes"))) do schemes[name] = scheme.new(name, {package = self}) end + -- add default scheme if no schemes are defined + if table.empty(schemes) then + schemes["__default__"] = scheme.new("__default__", {package = self}) + end self._SCHEMES = schemes end return schemes diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 5932f22a6..c2231543a 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -67,7 +67,11 @@ end -- get the scheme configuration function _instance:get(name) - return self._INFO:get(name) + local value = self._INFO:get(name) + if value == nil then + value = self:package():get(name) + end + return value end -- set the value to scheme info @@ -83,8 +87,8 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) local conf = self._INFO:extraconf(name, item, key) - if conf == nil and self:base() then - conf = self:base():extraconf(name, item, key) + if conf == nil then + conf = self:package():extraconf(name, item, key) end return conf end -- cgit v1.3.1 From c6a5ff9175d280d894126412112aa10db57e6ecb Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 5 Jan 2026 23:56:13 +0800 Subject: improve to load package --- xmake/core/package/package.lua | 17 ++++++++++++++++- xmake/modules/private/action/require/impl/package.lua | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index b6c444778..f5d550c52 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1110,10 +1110,18 @@ function _instance:_load() self._SOURCE_INITED = true local loaded = self._LOADED if not loaded then + + -- load on_load script local on_load = self:script("load") if on_load then on_load(self) end + + -- load all components + self:_load_components() + + -- load environments from the manifest to enable the environments of on_install() + self:_load_envs() end end @@ -1195,7 +1203,7 @@ function _instance:envs() end -- load the package environments from the manifest -function _instance:envs_load() +function _instance:_load_envs() local manifest = self:manifest_load() if manifest then local envs = self:_rawenvs() @@ -1205,6 +1213,13 @@ function _instance:envs_load() end end +-- load all components +function _instance:_load_components() + for _, component_inst in pairs(self:components()) do + component_inst:_load() + end +end + -- enter the package environments function _instance:envs_enter() local installdir = self:installdir({readonly = true}) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 90efb3751..842a6cd95 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -1033,6 +1033,7 @@ function _load_package(packagename, requireinfo, opt) -- load environments from the manifest to enable the environments of on_install() package:envs_load() + -- check api check_api(package, {load = true}) -- save this package package to cache -- cgit v1.3.1 From 05e58e9802b133ca6829031950279a871a394cbd Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 5 Jan 2026 23:56:33 +0800 Subject: load schemes --- xmake/core/package/package.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index f5d550c52..849ab4fdd 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1120,6 +1120,9 @@ function _instance:_load() -- load all components self:_load_components() + -- load all schemes + self:_load_schemes() + -- load environments from the manifest to enable the environments of on_install() self:_load_envs() end @@ -1220,6 +1223,13 @@ function _instance:_load_components() end end +-- load all schemes +function _instance:_load_schemes() + for _, scheme_inst in pairs(self:schemes()) do + scheme_inst:_load() + end +end + -- enter the package environments function _instance:envs_enter() local installdir = self:installdir({readonly = true}) -- cgit v1.3.1 From 60fcc1c6c008d17a5fd0fcf39ba5d9ed3a7c139e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 22:36:10 +0800 Subject: fix load packages --- xmake/modules/private/action/require/impl/package.lua | 8 -------- 1 file changed, 8 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 842a6cd95..eae010012 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -1025,14 +1025,6 @@ function _load_package(packagename, requireinfo, opt) -- do load package:_load() - -- load all components - for _, component in pairs(package:components()) do - component:_load() - end - - -- load environments from the manifest to enable the environments of on_install() - package:envs_load() - -- check api check_api(package, {load = true}) -- cgit v1.3.1 From a1aed61239dc4892d67668a120f6a78367dfde30 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 22:37:43 +0800 Subject: improve scheme:get --- xmake/core/package/package.lua | 7 +++---- xmake/core/package/scheme.lua | 9 +++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 849ab4fdd..75571f695 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2462,13 +2462,10 @@ function _instance:schemes() local schemes = self._SCHEMES if not schemes then schemes = {} + schemes["__default__"] = scheme.new("__default__", {package = self}) for _, name in ipairs(table.wrap(self:get("schemes"))) do schemes[name] = scheme.new(name, {package = self}) end - -- add default scheme if no schemes are defined - if table.empty(schemes) then - schemes["__default__"] = scheme.new("__default__", {package = self}) - end self._SCHEMES = schemes end return schemes @@ -2479,6 +2476,8 @@ function _instance:schemes_orderlist() local schemes_orderlist = self._SCHEMES_ORDERLIST if not schemes_orderlist then schemes_orderlist = {} + -- always add default scheme first + table.insert(schemes_orderlist, self:scheme("__default__")) for _, name in ipairs(table.wrap(self:get("schemes"))) do table.insert(schemes_orderlist, self:scheme(name)) end diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index c2231543a..18d3392a8 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -60,6 +60,11 @@ function _instance:type() return "scheme" end +-- is default scheme? +function _instance:is_default() + return self:name() == "__default__" +end + -- get the it's package function _instance:package() return self._PACKAGE @@ -68,7 +73,7 @@ end -- get the scheme configuration function _instance:get(name) local value = self._INFO:get(name) - if value == nil then + if value == nil and self:is_default() then value = self:package():get(name) end return value @@ -87,7 +92,7 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) local conf = self._INFO:extraconf(name, item, key) - if conf == nil then + if conf == nil and self:is_default() then conf = self:package():extraconf(name, item, key) end return conf -- cgit v1.3.1 From 5f6d3db9d4294ddb3f4ba2ded516e9409eb0e9f2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 22:47:30 +0800 Subject: add scheme test --- tests/projects/package/schemes/src/main.cpp | 6 ++ tests/projects/package/schemes/test.lua | 11 ++++ tests/projects/package/schemes/xmake.lua | 87 +++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 tests/projects/package/schemes/src/main.cpp create mode 100644 tests/projects/package/schemes/test.lua create mode 100644 tests/projects/package/schemes/xmake.lua diff --git a/tests/projects/package/schemes/src/main.cpp b/tests/projects/package/schemes/src/main.cpp new file mode 100644 index 000000000..4ca167f53 --- /dev/null +++ b/tests/projects/package/schemes/src/main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char** argv) { + std::cout << "Hello, schemes test!" << std::endl; + return 0; +} diff --git a/tests/projects/package/schemes/test.lua b/tests/projects/package/schemes/test.lua new file mode 100644 index 000000000..4c7bad3c2 --- /dev/null +++ b/tests/projects/package/schemes/test.lua @@ -0,0 +1,11 @@ +function main(t) + -- freebsd ci is slower + if is_host("bsd", "solaris") then + return + end + + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end +end diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua new file mode 100644 index 000000000..790b474ea --- /dev/null +++ b/tests/projects/package/schemes/xmake.lua @@ -0,0 +1,87 @@ +add_rules("mode.debug", "mode.release") + +package("cmake") + set_kind("binary") + set_homepage("https://cmake.org") + set_description("A cross-platform family of tools designed to build, test and package software") + + if is_host("macosx") then + add_urls("https://cmake.org/files/v$(version).tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") + end}) + add_versions("4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") + elseif is_host("linux") then + if os.arch():find("arm64.*") then + add_urls("https://cmake.org/files/v$(version)-aarch64.tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)-aarch64.tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + add_versions("4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") + else + add_urls("https://cmake.org/files/v$(version)-x86_64.tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)-x86_64.tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + add_versions("4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") + end + elseif is_host("windows") then + if os.arch() == "x64" then + add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") + end}) + add_versions("4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") + elseif os.arch() == "x86" then + add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") + end}) + add_versions("4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") + elseif os.arch() == "arm64" then + add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. "-windows-arm64" + end}) + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. "-windows-arm64" + end}) + add_versions("4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") + end + else + add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") + add_versions("4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + end + + on_install("@linux", "@windows", "@msys", "@cygwin", "@macosx", function (package) + local is_default = false + if is_default then + raise("trigger failure when installing binaries, then we will fallback to install it from source tarball.") + else + import("core.base.option") + os.vrunv("sh", {"./bootstrap", "--parallel=" .. (option.get("jobs") or tostring(os.default_njob())), + "--prefix=" .. package:installdir(), "--", "-DCMAKE_USE_OPENSSL=OFF"}) + import("package.tools.make").install(package) + end + end) + + on_test(function (package) + os.vrun("cmake --version") + end) +package_end() + +add_requires("cmake", {system = false}) + +target("test") + set_kind("binary") + add_files("src/*.cpp") + add_packages("cmake") -- cgit v1.3.1 From 8a1ef48e80ebd9248e1be0cf3eb6d9780dcd4855 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 22:55:04 +0800 Subject: add current scheme for package --- tests/projects/package/schemes/xmake.lua | 14 ++++++++++++-- xmake/core/package/package.lua | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua index 790b474ea..5cda14ea3 100644 --- a/tests/projects/package/schemes/xmake.lua +++ b/tests/projects/package/schemes/xmake.lua @@ -5,6 +5,7 @@ package("cmake") set_homepage("https://cmake.org") set_description("A cross-platform family of tools designed to build, test and package software") + local is_precompiled = true if is_host("macosx") then add_urls("https://cmake.org/files/v$(version).tar.gz", {version = function (version) return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") @@ -60,11 +61,20 @@ package("cmake") else add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") add_versions("4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + is_precompiled = false + end + + if is_precompiled then + add_schemes("source") + on_scheme("source", function (package, scheme) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") + scheme:add("versions", "4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + end) end on_install("@linux", "@windows", "@msys", "@cygwin", "@macosx", function (package) - local is_default = false - if is_default then + local scheme = package:current_scheme() + if scheme:is_default() then raise("trigger failure when installing binaries, then we will fallback to install it from source tarball.") else import("core.base.option") diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 75571f695..df24de0f2 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2451,7 +2451,27 @@ end -- get the given package scheme function _instance:scheme(name) - return self:schemes()[name] + if not name then + os.raise("scheme name is required") + end + local scheme = self:schemes()[name] + if not scheme then + os.raise("scheme %s not found", name) + end + return scheme +end + +-- set current scheme +function _instance:current_scheme_set(scheme) + self._CURRENT_SCHEME = scheme +end + +-- get current scheme +function _instance:current_scheme() + if self._CURRENT_SCHEME then + return self._CURRENT_SCHEME + end + return self:scheme("__default__") end -- get package schemes -- cgit v1.3.1 From 7e580d700a0872dd557ade75acd4d9cd625a78a8 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 23:19:53 +0800 Subject: update scheme test --- tests/projects/package/schemes/xmake.lua | 142 ++++++++++++++++++------------- 1 file changed, 83 insertions(+), 59 deletions(-) diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua index 5cda14ea3..7022523fc 100644 --- a/tests/projects/package/schemes/xmake.lua +++ b/tests/projects/package/schemes/xmake.lua @@ -5,76 +5,100 @@ package("cmake") set_homepage("https://cmake.org") set_description("A cross-platform family of tools designed to build, test and package software") - local is_precompiled = true - if is_host("macosx") then - add_urls("https://cmake.org/files/v$(version).tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") - end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") - end}) - add_versions("4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") - elseif is_host("linux") then - if os.arch():find("arm64.*") then - add_urls("https://cmake.org/files/v$(version)-aarch64.tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)-aarch64.tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - add_versions("4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") - else - add_urls("https://cmake.org/files/v$(version)-x86_64.tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)-x86_64.tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - add_versions("4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") + local function add_binary_urls(package, scheme_name) + local scheme = package + if scheme_name then + scheme = package:scheme(scheme_name) end - elseif is_host("windows") then - if os.arch() == "x64" then - add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") - end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") - end}) - add_versions("4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") - elseif os.arch() == "x86" then - add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") - end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") + if is_host("macosx") then + scheme:add("urls", "https://cmake.org/files/v$(version).tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") end}) - add_versions("4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") - elseif os.arch() == "arm64" then - add_urls("https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. "-windows-arm64" + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") end}) - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. "-windows-arm64" - end}) - add_versions("4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") + scheme:add("versions", "4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") + return true + elseif is_host("linux") then + if os.arch():find("arm64.*") then + scheme:add("urls", "https://cmake.org/files/v$(version)-aarch64.tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-aarch64.tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + scheme:add("versions", "4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") + else + scheme:add("urls", "https://cmake.org/files/v$(version)-x86_64.tar.gz", {version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-x86_64.tar.gz", {version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") + end}) + scheme:add("versions", "4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") + end + return true + elseif is_host("windows") then + if os.arch() == "x64" then + scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") + end}) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") + end}) + scheme:add("versions", "4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") + elseif os.arch() == "x86" then + scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") + end}) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") + end}) + scheme:add("versions", "4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") + elseif os.arch() == "arm64" then + scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. "-windows-arm64" + end}) + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) + return version .. "/cmake-" .. version .. "-windows-arm64" + end}) + scheme:add("versions", "4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") + end + return true end - else - add_urls("https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") - add_versions("4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") - is_precompiled = false end - if is_precompiled then - add_schemes("source") - on_scheme("source", function (package, scheme) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") - scheme:add("versions", "4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + local function add_source_urls(package, scheme_name) + local scheme = package + if scheme_name then + scheme = package:scheme(scheme_name) + end + scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") + scheme:add("versions", "4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + end + + if add_schemes then + add_schemes("binary", "source") + on_source(function (package) + add_binary_urls(package, "binary") + add_source_urls(package, "source") + end) + else + -- for compatibility with older xmake versions + on_source(function (package) + if add_binary_urls(package) then + package:data_set("scheme", "binary") + else + add_source_urls(package) + package:data_set("scheme", "source") + end end) end on_install("@linux", "@windows", "@msys", "@cygwin", "@macosx", function (package) local scheme = package:current_scheme() - if scheme:is_default() then + local scheme_name = scheme and scheme:name() or package:data("scheme") + if scheme_name and scheme_name == "binary" then raise("trigger failure when installing binaries, then we will fallback to install it from source tarball.") else import("core.base.option") -- cgit v1.3.1 From 2bf97997896c0522c4a0df4f233e62452f1c1ee9 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 23:20:22 +0800 Subject: remove default scheme --- xmake/core/package/package.lua | 3 --- xmake/core/package/scheme.lua | 17 ++--------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index df24de0f2..8c5fb3d8c 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2482,7 +2482,6 @@ function _instance:schemes() local schemes = self._SCHEMES if not schemes then schemes = {} - schemes["__default__"] = scheme.new("__default__", {package = self}) for _, name in ipairs(table.wrap(self:get("schemes"))) do schemes[name] = scheme.new(name, {package = self}) end @@ -2496,8 +2495,6 @@ function _instance:schemes_orderlist() local schemes_orderlist = self._SCHEMES_ORDERLIST if not schemes_orderlist then schemes_orderlist = {} - -- always add default scheme first - table.insert(schemes_orderlist, self:scheme("__default__")) for _, name in ipairs(table.wrap(self:get("schemes"))) do table.insert(schemes_orderlist, self:scheme(name)) end diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 18d3392a8..64159fd6d 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -60,11 +60,6 @@ function _instance:type() return "scheme" end --- is default scheme? -function _instance:is_default() - return self:name() == "__default__" -end - -- get the it's package function _instance:package() return self._PACKAGE @@ -72,11 +67,7 @@ end -- get the scheme configuration function _instance:get(name) - local value = self._INFO:get(name) - if value == nil and self:is_default() then - value = self:package():get(name) - end - return value + return self._INFO:get(name) end -- set the value to scheme info @@ -91,11 +82,7 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) - local conf = self._INFO:extraconf(name, item, key) - if conf == nil and self:is_default() then - conf = self:package():extraconf(name, item, key) - end - return conf + return self._INFO:extraconf(name, item, key) end -- set the extra configuration -- cgit v1.3.1 From 2c77aafe1a0c1b87c9b423541eaff4a04748e5e5 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 6 Jan 2026 23:21:05 +0800 Subject: remove load schemes --- xmake/core/package/package.lua | 10 ---------- xmake/core/package/scheme.lua | 28 ---------------------------- 2 files changed, 38 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 8c5fb3d8c..4f4ec06f0 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1120,9 +1120,6 @@ function _instance:_load() -- load all components self:_load_components() - -- load all schemes - self:_load_schemes() - -- load environments from the manifest to enable the environments of on_install() self:_load_envs() end @@ -1223,13 +1220,6 @@ function _instance:_load_components() end end --- load all schemes -function _instance:_load_schemes() - for _, scheme_inst in pairs(self:schemes()) do - scheme_inst:_load() - end -end - -- enter the package environments function _instance:envs_enter() local installdir = self:installdir({readonly = true}) diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 64159fd6d..7c8e61f2d 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -90,34 +90,6 @@ function _instance:extraconf_set(name, item, key, value) return self._INFO:extraconf_set(name, item, key, value) end --- get on_scheme script -function _instance:_on_scheme() - local script = self:package():get("scheme") - local result = nil - if type(script) == "function" then - result = script - elseif type(script) == "table" then - result = script[self:name()] - result = result or script["__generic__"] - end - return result -end - --- load this scheme -function _instance:_load() - local loaded = self._LOADED - if not loaded then - local script = self:_on_scheme() - if script then - local ok, errors = sandbox.load(script, self:package(), self) - if not ok then - os.raise("load scheme(%s) failed, %s", self:name(), errors or "unknown errors") - end - end - self._LOADED = true - end -end - -- interpreter function scheme._interpreter() local interp = scheme._INTERPRETER -- cgit v1.3.1 From 3b1f621c6b25958eef72dd98df074fcb6bc81d5e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 7 Jan 2026 23:56:51 +0800 Subject: improve to select package version for schemes --- tests/projects/package/schemes/xmake.lua | 12 +-- xmake/core/base/scopeinfo.lua | 4 - xmake/core/package/scheme.lua | 112 +++++++++++++++++++-- .../private/action/require/impl/package.lua | 54 +++++++--- 4 files changed, 149 insertions(+), 33 deletions(-) diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua index 7022523fc..6c6ae5bfe 100644 --- a/tests/projects/package/schemes/xmake.lua +++ b/tests/projects/package/schemes/xmake.lua @@ -17,7 +17,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).tar.gz", {version = function (version) return version .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") end}) - scheme:add("versions", "4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") + scheme:add("versions", "4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") return true elseif is_host("linux") then if os.arch():find("arm64.*") then @@ -27,7 +27,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-aarch64.tar.gz", {version = function (version) return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") end}) - scheme:add("versions", "4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") + scheme:add("versions", "4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") else scheme:add("urls", "https://cmake.org/files/v$(version)-x86_64.tar.gz", {version = function (version) return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") @@ -35,7 +35,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-x86_64.tar.gz", {version = function (version) return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") end}) - scheme:add("versions", "4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") + scheme:add("versions", "4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") end return true elseif is_host("windows") then @@ -46,7 +46,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") end}) - scheme:add("versions", "4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") + scheme:add("versions", "4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") elseif os.arch() == "x86" then scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") @@ -54,7 +54,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") end}) - scheme:add("versions", "4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") + scheme:add("versions", "4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") elseif os.arch() == "arm64" then scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. "-windows-arm64" @@ -62,7 +62,7 @@ package("cmake") scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) return version .. "/cmake-" .. version .. "-windows-arm64" end}) - scheme:add("versions", "4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") + scheme:add("versions", "4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") end return true end diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 2fd362475..f088cf8ae 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -359,11 +359,7 @@ end -- add the api dictionary to the scope info function _instance:_api_add_dictionary(name, dict_or_key, value, extra_config) - - -- get the scope info local scope = self._INFO - - -- check scope[name] = scope[name] or {} if type(dict_or_key) == "table" then local dict = {} diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 7c8e61f2d..a7166283a 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -90,6 +90,107 @@ function _instance:extraconf_set(name, item, key, value) return self._INFO:extraconf_set(name, item, key, value) end +-- get urls +function _instance:urls() + local urls = self._URLS + if urls == nil then + urls = table.wrap(self:get("urls")) + if #urls == 1 and urls[1] == "" then + urls = {} + end + end + return urls +end + +-- get versions +function _instance:versions() + if self._VERSIONS == nil then + -- we need to sort the build number in semver list + -- https://github.com/xmake-io/xmake/issues/6953 + local versions = {} + for version, _ in table.orderpairs(self:_versions_list()) do + -- remove the url alias prefix if exists + local pos = version:find(':', 1, true) + if pos then + version = version:sub(pos + 1, -1) + end + table.insert(versions, version) + end + self._VERSIONS = table.unique(versions) + end + return self._VERSIONS +end + +-- get versions list +function _instance:_versions_list() + if self._VERSIONS_LIST == nil then + local versions = table.wrap(self:get("versions")) + local versionfiles = self:get("versionfiles") + if versionfiles then + for _, versionfile in ipairs(table.wrap(versionfiles)) do + if not path.is_absolute(versionfile) then + local subpath = versionfile + versionfile = path.join(self:scriptdir(), subpath) + if not os.isfile(versionfile) and self:package() then + versionfile = path.join(self:package():scriptdir(), subpath) + end + end + if os.isfile(versionfile) then + local list = io.readfile(versionfile) + for _, line in ipairs(list:split("\n")) do + local splitinfo = line:split("%s+") + if #splitinfo == 2 then + local version = splitinfo[1] + local shasum = splitinfo[2] + versions[version] = shasum + end + end + end + end + end + self._VERSIONS_LIST = versions + end + return self._VERSIONS_LIST +end + +-- get version string +function _instance:version_str() + return self._VERSION_STR +end + +-- set version +function _instance:version_set(version, source) + self._VERSION_STR = version + self._VERSION_SOURCE = source + if source == "branch" then + self._BRANCH = version + elseif source == "tag" then + self._TAG = version + elseif source == "commit" then + self._COMMIT = version + end +end + +-- get branch version +function _instance:branch() + return self._BRANCH +end + +-- get tag version +function _instance:tag() + return self._TAG +end + +-- get commit version +function _instance:commit() + return self._COMMIT +end + +-- is git ref? +function _instance:gitref() + return self:branch() or self:tag() or self:commit() +end + -- interpreter function scheme._interpreter() local interp = scheme._INTERPRETER @@ -107,19 +208,12 @@ function scheme.apis() values = { -- scheme.set_xxx "scheme.set_urls", - "scheme.set_policy", -- scheme.add_xxx - "scheme.add_urls", - "scheme.add_patches", - "scheme.add_resources", - "scheme.add_versionfiles", - "scheme.add_versions" + "scheme.add_urls" }, keyvalues = { - -- scheme.set_xxx - "scheme.set_policy" -- scheme.add_xxx - , "scheme.add_patches" + "scheme.add_patches" , "scheme.add_resources" }, paths = { diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index eae010012..2b55d6834 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -342,20 +342,8 @@ function _add_package_configurations(package) package:add("configs", "shflags", {builtin = true, description = "Set the shared library linker flags."}) end --- select package version -function _select_package_version(package, requireinfo, locked_requireinfo) - - -- get it from the locked requireinfo - if locked_requireinfo then - local version = locked_requireinfo.version - local source = "version" - if locked_requireinfo.branch then - source = "branch" - elseif locked_requireinfo.tag then - source = "tag" - end - return version, source - end +-- select version from package or scheme +function _select_version_from(package, requireinfo) -- has git url? local has_giturl = false @@ -397,6 +385,44 @@ function _select_package_version(package, requireinfo, locked_requireinfo) version = "latest" source = "version" end + return version, source +end + +-- select package version +function _select_package_version(package, requireinfo, locked_requireinfo) + + -- get it from the locked requireinfo + if locked_requireinfo then + local version = locked_requireinfo.version + local source = "version" + if locked_requireinfo.branch then + source = "branch" + elseif locked_requireinfo.tag then + source = "tag" + end + return version, source + end + + -- select version from package or schemes + local version, source + local schemes = package:schemes_orderlist() + if schemes then + for _, scheme in ipairs(schemes) do + local scheme_version, scheme_source = _select_version_from(scheme, requireinfo) + if scheme_version then + scheme:version_set(scheme_version, scheme_source) + if version then + assert(scheme_version == version, "package(%s): the version lists of schemes are mismatch.") + else + version = scheme_version + source = scheme_source + end + end + end + else + version, source = _select_version_from(package, requireinfo) + end + if not version and not package:is_thirdparty() and is_system ~= true then raise("package(%s): version(%s) not found!", package:name(), require_version) end -- cgit v1.3.1 From 5a0021308f56cd3399425e87945d66839753c5c3 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 00:53:46 +0800 Subject: improve schemes --- xmake/core/package/package.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 4f4ec06f0..a3e09217c 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2458,10 +2458,7 @@ end -- get current scheme function _instance:current_scheme() - if self._CURRENT_SCHEME then - return self._CURRENT_SCHEME - end - return self:scheme("__default__") + return self._CURRENT_SCHEME end -- get package schemes @@ -2472,8 +2469,8 @@ function _instance:schemes() local schemes = self._SCHEMES if not schemes then schemes = {} - for _, name in ipairs(table.wrap(self:get("schemes"))) do - schemes[name] = scheme.new(name, {package = self}) + for _, scheme in ipairs(self:schemes_orderlist()) do + schemes[scheme:name()] = scheme end self._SCHEMES = schemes end @@ -2485,8 +2482,12 @@ function _instance:schemes_orderlist() local schemes_orderlist = self._SCHEMES_ORDERLIST if not schemes_orderlist then schemes_orderlist = {} - for _, name in ipairs(table.wrap(self:get("schemes"))) do - table.insert(schemes_orderlist, self:scheme(name)) + local scheme_names = table.wrap(self:get("schemes")) + if #scheme_names == 0 then + scheme_names = {"__default__"} + end + for _, name in ipairs(scheme_names) do + table.insert(schemes_orderlist, scheme.new(name, {package = self})) end self._SCHEMES_ORDERLIST = schemes_orderlist end -- cgit v1.3.1 From f2184314dfa6d218bc6e0383386ec8bdd7bb8ef2 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 00:54:34 +0800 Subject: add default scheme --- xmake/core/package/package.lua | 1 + xmake/core/package/scheme.lua | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index a3e09217c..60391c745 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2490,6 +2490,7 @@ function _instance:schemes_orderlist() table.insert(schemes_orderlist, scheme.new(name, {package = self})) end self._SCHEMES_ORDERLIST = schemes_orderlist + self._CURRENT_SCHEME = schemes_orderlist[1] end return schemes_orderlist end diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index a7166283a..1aa392437 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -60,6 +60,11 @@ function _instance:type() return "scheme" end +-- is default scheme? +function _instance:is_default() + return self:name() == "__default__" +end + -- get the it's package function _instance:package() return self._PACKAGE @@ -67,7 +72,11 @@ end -- get the scheme configuration function _instance:get(name) - return self._INFO:get(name) + local value = self._INFO:get(name) + if value == nil and self:is_default() and self:package() then + value = self:package():get(name) + end + return value end -- set the value to scheme info @@ -82,7 +91,11 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) - return self._INFO:extraconf(name, item, key) + local value = self._INFO:extraconf(name, item, key) + if value == nil and self:is_default() and self:package() then + value = self:package():extraconf(name, item, key) + end + return value end -- set the extra configuration -- cgit v1.3.1 From 7d476913ae7909abd9fabb45e7bb4cca910f9635 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 00:56:54 +0800 Subject: improve package to use current scheme --- xmake/core/package/package.lua | 124 ++++++----------------------------------- xmake/core/package/scheme.lua | 100 +++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 110 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 60391c745..96702109c 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -327,47 +327,40 @@ end -- get urls function _instance:urls() - local urls = self._URLS - if urls == nil then - urls = table.wrap(self:get("urls")) - if #urls == 1 and urls[1] == "" then - urls = {} - end - end - return urls + return self:current_scheme():urls() end -- get urls function _instance:urls_set(urls) - self._URLS = urls + self:current_scheme():urls_set(urls) end -- get the alias of url, @note need raw url function _instance:url_alias(url) - return self:extraconf("urls", url, "alias") + return self:current_scheme():url_alias(url) end -- get the version filter of url, @note need raw url function _instance:url_version(url) - return self:extraconf("urls", url, "version") + return self:current_scheme():url_version(url) end -- get the excludes paths of url -- @note it supports the path pattern, but it only supports for archiver. function _instance:url_excludes(url) - return self:extraconf("urls", url, "excludes") + return self:current_scheme():url_excludes(url) end -- get the includes paths of url -- @note it does not support the path pattern, and it only supports for git url now. -- @see https://github.com/xmake-io/xmake/issues/6071 function _instance:url_includes(url) - return self:extraconf("urls", url, "includes") + return self:current_scheme():url_includes(url) end -- get the http headers of url, @note need raw url function _instance:url_http_headers(url) - return self:extraconf("urls", url, "http_headers") + return self:current_scheme():url_http_headers(url) end -- set artifacts info @@ -546,30 +539,12 @@ end -- get hash of the source package for the url_alias@version_str function _instance:sourcehash(url_alias) - local versions = self:_versions_list() - local version_str = self:version_str() - if versions and version_str then - local sourcehash = nil - if url_alias then - sourcehash = versions[url_alias .. ":" ..version_str] - end - if not sourcehash then - sourcehash = versions[version_str] - end - if sourcehash and #sourcehash == 40 then - sourcehash = sourcehash:lower() - end - return sourcehash - end + return self:current_scheme():sourcehash(url_alias) end -- get revision(commit, tag, branch) of the url_alias@version_str, only for git url function _instance:revision(url_alias) - local revision = self:sourcehash(url_alias) - if revision and #revision <= 40 then - -- it will be sha256 of tar/gz file, not commit number if longer than 40 characters - return revision - end + return self:current_scheme():revision(url_alias) end -- get the package policy @@ -1485,58 +1460,17 @@ end -- get versions list function _instance:_versions_list() - if self._VERSIONS_LIST == nil then - local versions = table.wrap(self:get("versions")) - local versionfiles = self:get("versionfiles") - if versionfiles then - for _, versionfile in ipairs(table.wrap(versionfiles)) do - if not path.is_absolute(versionfile) then - local subpath = versionfile - versionfile = path.join(self:scriptdir(), subpath) - if not os.isfile(versionfile) and self:base() then - versionfile = path.join(self:base():scriptdir(), subpath) - end - end - if os.isfile(versionfile) then - local list = io.readfile(versionfile) - for _, line in ipairs(list:split("\n")) do - local splitinfo = line:split("%s+") - if #splitinfo == 2 then - local version = splitinfo[1] - local shasum = splitinfo[2] - versions[version] = shasum - end - end - end - end - end - self._VERSIONS_LIST = versions - end - return self._VERSIONS_LIST + return self:current_scheme():_versions_list() end -- get versions function _instance:versions() - if self._VERSIONS == nil then - -- we need to sort the build number in semver list - -- https://github.com/xmake-io/xmake/issues/6953 - local versions = {} - for version, _ in table.orderpairs(self:_versions_list()) do - -- remove the url alias prefix if exists - local pos = version:find(':', 1, true) - if pos then - version = version:sub(pos + 1, -1) - end - table.insert(versions, version) - end - self._VERSIONS = table.unique(versions) - end - return self._VERSIONS + return self:current_scheme():versions() end -- get the version function _instance:version() - return self._VERSION + return self:current_scheme():version() end -- get the version string @@ -1547,54 +1481,32 @@ function _instance:version_str() return requireinfo.version end end - return self._VERSION_STR + return self:current_scheme():version_str() end -- set the version, source: branch, tag, version function _instance:version_set(version, source) - - -- save the semver version - local sv = semver.new(version) - if sv then - self._VERSION = sv - end - - -- save branch and tag - if source == "branch" then - self._BRANCH = version - elseif source == "tag" then - self._TAG = version - elseif source == "commit" then - self._COMMIT = version - end - - -- save version string - if source == "commit" then - -- we strip it to avoid long paths - self._VERSION_STR = version:sub(1, 8) - else - self._VERSION_STR = version - end + self:current_scheme():version_set(version, source) end -- get branch version function _instance:branch() - return self._BRANCH + return self:current_scheme():branch() end -- get tag version function _instance:tag() - return self._TAG + return self:current_scheme():tag() end -- get commit version function _instance:commit() - return self._COMMIT + return self:current_scheme():commit() end -- is git ref? function _instance:gitref() - return self:branch() or self:tag() or self:commit() + return self:current_scheme():gitref() end -- get the require info diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 1aa392437..10f906750 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -115,6 +115,51 @@ function _instance:urls() return urls end +-- set urls +function _instance:urls_set(urls) + self._URLS = urls +end + +-- get the alias of url, @note need raw url +function _instance:url_alias(url) + return self:extraconf("urls", url, "alias") +end + +-- get the version filter of url, @note need raw url +function _instance:url_version(url) + return self:extraconf("urls", url, "version") +end + +-- get the excludes paths of url +-- @note it supports the path pattern, but it only supports for archiver. +function _instance:url_excludes(url) + return self:extraconf("urls", url, "excludes") +end + +-- get the includes paths of url +-- @note it does not support the path pattern, and it only supports for git url now. +-- @see https://github.com/xmake-io/xmake/issues/6071 +function _instance:url_includes(url) + return self:extraconf("urls", url, "includes") +end + +-- get the http headers of url, @note need raw url +function _instance:url_http_headers(url) + return self:extraconf("urls", url, "http_headers") +end + +-- get the script directory +function _instance:scriptdir() + local scriptdir = self._SCRIPTDIR + if not scriptdir then + if self:package() then + scriptdir = self:package():scriptdir() + end + self._SCRIPTDIR = scriptdir + end + return scriptdir +end + -- get versions function _instance:versions() if self._VERSIONS == nil then @@ -144,8 +189,8 @@ function _instance:_versions_list() if not path.is_absolute(versionfile) then local subpath = versionfile versionfile = path.join(self:scriptdir(), subpath) - if not os.isfile(versionfile) and self:package() then - versionfile = path.join(self:package():scriptdir(), subpath) + if not os.isfile(versionfile) and self:package() and self:package():base() then + versionfile = path.join(self:package():base():scriptdir(), subpath) end end if os.isfile(versionfile) then @@ -166,6 +211,11 @@ function _instance:_versions_list() return self._VERSIONS_LIST end +-- get version +function _instance:version() + return self._VERSION +end + -- get version string function _instance:version_str() return self._VERSION_STR @@ -173,8 +223,14 @@ end -- set version function _instance:version_set(version, source) - self._VERSION_STR = version - self._VERSION_SOURCE = source + + -- save the semver version + local sv = semver.new(version) + if sv then + self._VERSION = sv + end + + -- save branch and tag if source == "branch" then self._BRANCH = version elseif source == "tag" then @@ -182,6 +238,14 @@ function _instance:version_set(version, source) elseif source == "commit" then self._COMMIT = version end + + -- save version string + if source == "commit" then + -- we strip it to avoid long paths + self._VERSION_STR = version:sub(1, 8) + else + self._VERSION_STR = version + end end -- get branch version @@ -204,6 +268,34 @@ function _instance:gitref() return self:branch() or self:tag() or self:commit() end +-- get hash of the source package for the url_alias@version_str +function _instance:sourcehash(url_alias) + local versions = self:_versions_list() + local version_str = self:version_str() + if versions and version_str then + local sourcehash = nil + if url_alias then + sourcehash = versions[url_alias .. ":" ..version_str] + end + if not sourcehash then + sourcehash = versions[version_str] + end + if sourcehash and #sourcehash == 40 then + sourcehash = sourcehash:lower() + end + return sourcehash + end +end + +-- get revision(commit, tag, branch) of the url_alias@version_str, only for git url +function _instance:revision(url_alias) + local revision = self:sourcehash(url_alias) + if revision and #revision <= 40 then + -- it will be sha256 of tar/gz file, not commit number if longer than 40 characters + return revision + end +end + -- interpreter function scheme._interpreter() local interp = scheme._INTERPRETER -- cgit v1.3.1 From 6265a6fcec0471720bf399374ca1078451036c43 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 22:39:37 +0800 Subject: improve to select version --- .../private/action/require/impl/package.lua | 38 ++++++++++------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 2b55d6834..2c1cf98fb 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -342,12 +342,12 @@ function _add_package_configurations(package) package:add("configs", "shflags", {builtin = true, description = "Set the shared library linker flags."}) end --- select version from package or scheme -function _select_version_from(package, requireinfo) +-- select version from scheme +function _select_version_from_scheme(scheme, requireinfo) -- has git url? local has_giturl = false - for _, url in ipairs(package:urls()) do + for _, url in ipairs(scheme:urls()) do if git.checkurl(url) then has_giturl = true break @@ -360,7 +360,7 @@ function _select_version_from(package, requireinfo) local require_version = requireinfo.version local require_verify = requireinfo.verify local is_system = requireinfo.system - local has_versionlist = package:get("versions") or package:get("versionfiles") + local has_versionlist = scheme:get("versions") or scheme:get("versionfiles") if (not has_versionlist or require_verify == false) and (semver.is_valid(require_version) or semver.is_valid_range(require_version)) then -- no version list in package() or need not verify sha256sum? try selecting this version directly @@ -370,8 +370,8 @@ function _select_version_from(package, requireinfo) -- https://github.com/xmake-io/xmake/issues/3551 version = require_version source = "version" - elseif #package:versions() > 0 then -- select version? - version, source = try { function () return semver.select(require_version, package:versions()) end } + elseif #scheme:versions() > 0 then -- select version? + version, source = try { function () return semver.select(require_version, scheme:versions()) end } end if not version and has_giturl then -- select branch? if require_version and #require_version == 40 and require_version:match("%w+") then @@ -381,7 +381,7 @@ function _select_version_from(package, requireinfo) end end -- local source package? we use a phony version - if not version and require_version == "latest" and #package:urls() == 0 then + if not version and require_version == "latest" and #scheme:urls() == 0 then version = "latest" source = "version" end @@ -403,24 +403,20 @@ function _select_package_version(package, requireinfo, locked_requireinfo) return version, source end - -- select version from package or schemes + -- select version from schemes local version, source local schemes = package:schemes_orderlist() - if schemes then - for _, scheme in ipairs(schemes) do - local scheme_version, scheme_source = _select_version_from(scheme, requireinfo) - if scheme_version then - scheme:version_set(scheme_version, scheme_source) - if version then - assert(scheme_version == version, "package(%s): the version lists of schemes are mismatch.") - else - version = scheme_version - source = scheme_source - end + for _, scheme in ipairs(schemes) do + local scheme_version, scheme_source = _select_version_from_scheme(scheme, requireinfo) + if scheme_version then + scheme:version_set(scheme_version, scheme_source) + if version then + assert(scheme_version == version, "package(%s): the version lists of schemes are mismatch.") + else + version = scheme_version + source = scheme_source end end - else - version, source = _select_version_from(package, requireinfo) end if not version and not package:is_thirdparty() and is_system ~= true then -- cgit v1.3.1 From 90b6cc257a135cdeafbc542d2ec368250f0ec69d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 22:53:42 +0800 Subject: install package from schemes --- .../action/require/impl/actions/install.lua | 7 ++-- .../action/require/impl/install_packages.lua | 37 +++++++++++----------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index d7310149a..157424305 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -555,8 +555,11 @@ function main(package) end os.tryrm(installdir) - -- is precompiled package? we can fallback to source package and try reinstall it again - if package:is_precompiled() then + -- is not last scheme? we can fallback to next scheme and try reinstall it again + local current_scheme = package:current_scheme() + local schemes_orderlist = package:schemes_orderlist() + local last_scheme = schemes_orderlist[#schemes_orderlist] + if current_scheme ~= last_scheme then ok = false else -- failed diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 39d7d0bd4..1585c55cc 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -495,25 +495,26 @@ function _do_install_packages(packages_install, packages_download, installdeps) packages_in_group[group] = 0 end - -- download this package first - local downloaded = true - if packages_download[tostring(instance)] then - packages_downloading[index] = instance - action_check(instance) - downloaded = action_download(instance) - packages_downloading[index] = nil - end - - -- install this package - packages_installing[index] = instance - if downloaded then - if not action_install(instance) then - assert(instance:is_precompiled(), "package(%s) should be precompiled", instance:name()) - -- we need to disable built and re-download and re-install it - instance:fallback_build() + -- install package from the multiple schemes + for _, scheme in ipairs(instance:schemes_orderlist()) do + instance:current_scheme_set(scheme) + + -- download this package first + local downloaded = true + if packages_download[tostring(instance)] then + packages_downloading[index] = instance + packages_installing[index] = nil action_check(instance) - action_download(instance) - action_install(instance) + downloaded = action_download(instance) + packages_downloading[index] = nil + end + + packages_installing[index] = instance + if downloaded then + if action_install(instance) then + -- install ok + break + end end end -- cgit v1.3.1 From f3c2a43971a0562270cc07320904b0c8a78e10e4 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 22:55:36 +0800 Subject: move patches and resources to scheme --- xmake/core/package/package.lua | 68 ++--------------------------------- xmake/core/package/scheme.lua | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 96702109c..b2b9d052e 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1475,12 +1475,6 @@ end -- get the version string function _instance:version_str() - if self:is_thirdparty() then - local requireinfo = self:requireinfo() - if requireinfo then - return requireinfo.version - end - end return self:current_scheme():version_str() end @@ -2153,70 +2147,12 @@ end -- @endcode -- function _instance:patches() - local patches = self._PATCHES - if patches == nil then - local patchinfos = self:get("patches") - if patchinfos then - local version_str = self:version_str() - local patchinfo = patchinfos[version_str] - if patchinfo then - patches = {} - patchinfo = table.wrap(patchinfo) - for idx = 1, #patchinfo, 2 do - local extra = self:extraconf("patches." .. version_str, patchinfo[idx]) - table.insert(patches , {url = patchinfo[idx], sha256 = patchinfo[idx + 1], extra = extra}) - end - else - -- match semver, e.g add_patches(">=1.0.0", url, sha256) - for range, patchinfo in pairs(patchinfos) do - if semver.satisfies(version_str, range) then - patches = patches or {} - patchinfo = table.wrap(patchinfo) - for idx = 1, #patchinfo, 2 do - local extra = self:extraconf("patches." .. range, patchinfo[idx]) - table.insert(patches , {url = patchinfo[idx], sha256 = patchinfo[idx + 1], extra = extra}) - end - end - end - end - end - self._PATCHES = patches or false - end - return patches and patches or nil + return self:current_scheme():patches() end -- get the resources of the current version function _instance:resources() - local resources = self._RESOURCES - if resources == nil then - local resourceinfos = self:get("resources") - if resourceinfos then - local version_str = self:version_str() - local resourceinfo = resourceinfos[version_str] - if resourceinfo then - resources = {} - resourceinfo = table.wrap(resourceinfo) - for idx = 1, #resourceinfo, 3 do - local name = resourceinfo[idx] - resources[name] = {url = resourceinfo[idx + 1], sha256 = resourceinfo[idx + 2]} - end - else - -- match semver, e.g add_resources(">=1.0.0", name, url, sha256) - for range, resourceinfo in pairs(resourceinfos) do - if semver.satisfies(version_str, range) then - resources = resources or {} - resourceinfo = table.wrap(resourceinfo) - for idx = 1, #resourceinfo, 3 do - local name = resourceinfo[idx] - resources[name] = {url = resourceinfo[idx + 1], sha256 = resourceinfo[idx + 2]} - end - end - end - end - end - self._RESOURCES = resources or false - end - return resources and resources or nil + return self:current_scheme():resources() end -- get the the given resource diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 10f906750..94a2a7d02 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -218,6 +218,13 @@ end -- get version string function _instance:version_str() + local package = self:package() + if package and package:is_thirdparty() then + local requireinfo = package:requireinfo() + if requireinfo then + return requireinfo.version + end + end return self._VERSION_STR end @@ -296,6 +303,80 @@ function _instance:revision(url_alias) end end +-- get the patches of the current version +-- +-- @code +-- add_patches("6.7.6", "https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.7.6.xz", +-- "a394326aa325f8a930a4ce33c69ba7b8b454aef1107a4d3c2a8ae12908615fc4", {reverse = true}) +-- @endcode +-- +function _instance:patches() + local patches = self._PATCHES + if patches == nil then + local patchinfos = self:get("patches") + if patchinfos then + local version_str = self:version_str() + local patchinfo = patchinfos[version_str] + if patchinfo then + patches = {} + patchinfo = table.wrap(patchinfo) + for idx = 1, #patchinfo, 2 do + local extra = self:extraconf("patches." .. version_str, patchinfo[idx]) + table.insert(patches , {url = patchinfo[idx], sha256 = patchinfo[idx + 1], extra = extra}) + end + else + -- match semver, e.g add_patches(">=1.0.0", url, sha256) + for range, patchinfo in pairs(patchinfos) do + if semver.satisfies(version_str, range) then + patches = patches or {} + patchinfo = table.wrap(patchinfo) + for idx = 1, #patchinfo, 2 do + local extra = self:extraconf("patches." .. range, patchinfo[idx]) + table.insert(patches , {url = patchinfo[idx], sha256 = patchinfo[idx + 1], extra = extra}) + end + end + end + end + end + self._PATCHES = patches or false + end + return patches and patches or nil +end + +-- get the resources of the current version +function _instance:resources() + local resources = self._RESOURCES + if resources == nil then + local resourceinfos = self:get("resources") + if resourceinfos then + local version_str = self:version_str() + local resourceinfo = resourceinfos[version_str] + if resourceinfo then + resources = {} + resourceinfo = table.wrap(resourceinfo) + for idx = 1, #resourceinfo, 3 do + local name = resourceinfo[idx] + resources[name] = {url = resourceinfo[idx + 1], sha256 = resourceinfo[idx + 2]} + end + else + -- match semver, e.g add_resources(">=1.0.0", name, url, sha256) + for range, resourceinfo in pairs(resourceinfos) do + if semver.satisfies(version_str, range) then + resources = resources or {} + resourceinfo = table.wrap(resourceinfo) + for idx = 1, #resourceinfo, 3 do + local name = resourceinfo[idx] + resources[name] = {url = resourceinfo[idx + 1], sha256 = resourceinfo[idx + 2]} + end + end + end + end + end + self._RESOURCES = resources or false + end + return resources and resources or nil +end + -- interpreter function scheme._interpreter() local interp = scheme._INTERPRETER -- cgit v1.3.1 From cabdd8b0bf48356b7ffb9e6bb8d776cb4813f301 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Jan 2026 23:01:45 +0800 Subject: use ninja instead of cmake in scheme test --- tests/projects/package/schemes/port/xmake.lua | 87 +++++++++++++++++++++++++++ tests/projects/package/schemes/xmake.lua | 80 ++++++------------------ 2 files changed, 106 insertions(+), 61 deletions(-) create mode 100644 tests/projects/package/schemes/port/xmake.lua diff --git a/tests/projects/package/schemes/port/xmake.lua b/tests/projects/package/schemes/port/xmake.lua new file mode 100644 index 000000000..7cf73fc43 --- /dev/null +++ b/tests/projects/package/schemes/port/xmake.lua @@ -0,0 +1,87 @@ +includes("@builtin/check") + +add_rules("mode.release", "mode.debug") + +option("version", {description = "The ninja version."}) +set_version("$(version)") + +set_languages("c++14") +check_cfuncs("USE_PPOLL=1", "ppoll", {includes = "poll.h"}) + +target("libninja") + set_kind("$(kind)") + set_basename("ninja") + + add_files("src/build_log.cc") + add_files("src/build.cc") + add_files("src/clean.cc") + add_files("src/clparser.cc") + add_files("src/debug_flags.cc") + add_files("src/deps_log.cc") + add_files("src/disk_interface.cc") + add_files("src/edit_distance.cc") + add_files("src/eval_env.cc") + add_files("src/graph.cc") + add_files("src/graphviz.cc") + add_files("src/line_printer.cc") + add_files("src/manifest_parser.cc") + add_files("src/metrics.cc") + add_files("src/state.cc") + add_files("src/string_piece_util.cc") + add_files("src/util.cc") + add_files("src/version.cc") + add_files("src/depfile_parser.cc", "src/lexer.cc") + + if is_plat("windows") then + add_files("src/subprocess-win32.cc") + add_files("src/includes_normalize-win32.cc") + add_files("src/msvc_helper-win32.cc") + add_files("src/msvc_helper_main-win32.cc") + add_files("src/getopt.c", {sourcekind = "cxx"}) + add_files("src/minidump-win32.cc") + + add_defines("NOMINMAX") + else + add_files("src/subprocess-posix.cc") + end + + if is_plat("mingw") then + add_defines("_WIN32_WINNT=0x0601", "__USE_MINGW_ANSI_STDIO=1") + end + + on_load(function (target) + import("core.base.semver") + local version = semver.new(target:version()) + if version:ge("1.13.1") then + target:add("files", "src/elide_middle.cc") + target:add("files", "src/jobserver.cc") + target:add("files", "src/real_command_runner.cc") + target:add("files", "src/status_printer.cc") + if target:is_plat("windows") then + target:add("files", "src/jobserver-win32.cc") + else + target:add("files", "src/jobserver-posix.cc") + end + end + if version:ge("1.11.0") then + if version:lt("1.13.1") then + target:add("files", "src/status.cc") + end + target:add("files", "src/json.cc") + target:add("files", "src/missing_deps.cc") + end + if version:ge("1.10.0") then + target:add("files", "src/dyndep.cc") + target:add("files", "src/dyndep_parser.cc") + target:add("files", "src/parser.cc") + end + end) + +target("ninja") + set_kind("binary") + add_deps("libninja") + + add_files("src/ninja.cc") + if is_plat("windows") then + add_files("windows/ninja.manifest") + end diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua index 6c6ae5bfe..689b9c88d 100644 --- a/tests/projects/package/schemes/xmake.lua +++ b/tests/projects/package/schemes/xmake.lua @@ -1,69 +1,27 @@ add_rules("mode.debug", "mode.release") -package("cmake") +package("ninja") set_kind("binary") - set_homepage("https://cmake.org") - set_description("A cross-platform family of tools designed to build, test and package software") + set_homepage("https://ninja-build.org/") + set_description("Small build system for use with gyp or CMake.") local function add_binary_urls(package, scheme_name) local scheme = package if scheme_name then scheme = package:scheme(scheme_name) end + if is_host("macosx") then - scheme:add("urls", "https://cmake.org/files/v$(version).tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-macos-universal" or "-Darwin-x86_64") - end}) - scheme:add("versions", "4.2.1", "0bb18f295e52d7e9309980e361e79e76a1d8da67a1587255cbe3696ea998f597") + scheme:add("urls", "https://github.com/ninja-build/ninja/releases/download/v$(version)/ninja-mac.zip") + scheme:add("versions", "1.13.1", "da7797794153629aca5570ef7c813342d0be214ba84632af886856e8f0063dd9") return true elseif is_host("linux") then - if os.arch():find("arm64.*") then - scheme:add("urls", "https://cmake.org/files/v$(version)-aarch64.tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-aarch64.tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - scheme:add("versions", "4.2.1", "3e178207a2c42af4cd4883127f8800b6faf99f3f5187dccc68bfb2cc7808f5f7") - else - scheme:add("urls", "https://cmake.org/files/v$(version)-x86_64.tar.gz", {version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)-x86_64.tar.gz", {version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-linux" or "-Linux") - end}) - scheme:add("versions", "4.2.1", "c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980") - end + scheme:add("urls", "https://github.com/ninja-build/ninja/releases/download/v$(version)/ninja-linux.zip") + scheme:add("versions", "1.13.1", "0830252db77884957a1a4b87b05a1e2d9b5f658b8367f82999a941884cbe0238") return true elseif is_host("windows") then - if os.arch() == "x64" then - scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-x86_64" or "-win64-x64") - end}) - scheme:add("versions", "4.2.1", "dfc2b2afac257555e3b9ce375b12b2883964283a366c17fec96cf4d17e4f1677") - elseif os.arch() == "x86" then - scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. (version:ge("3.20") and "-windows-i386" or "-win32-x86") - end}) - scheme:add("versions", "4.2.1", "696129556482da90293f9d64c1fa68dbe06b0ede80331d7da9aaa03aada6aecf") - elseif os.arch() == "arm64" then - scheme:add("urls", "https://cmake.org/files/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return table.concat(table.slice((version):split('%.'), 1, 2), '.') .. "/cmake-" .. version .. "-windows-arm64" - end}) - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version).zip", {excludes = {"*/doc/*"}, version = function (version) - return version .. "/cmake-" .. version .. "-windows-arm64" - end}) - scheme:add("versions", "4.2.1", "96b097ca3a019cd62839d4805958ad0163dd1adedcfbe578730d57c098aaf667") - end + scheme:add("urls", "https://github.com/ninja-build/ninja/releases/download/v$(version)/ninja-win.zip") + scheme:add("versions", "1.13.1", "26a40fa8595694dec2fad4911e62d29e10525d2133c9a4230b66397774ae25bf") return true end end @@ -73,8 +31,8 @@ package("cmake") if scheme_name then scheme = package:scheme(scheme_name) end - scheme:add("urls", "https://github.com/Kitware/CMake/releases/download/v$(version)/cmake-$(version).tar.gz") - scheme:add("versions", "4.2.1", "414aacfac54ba0e78e64a018720b64ed6bfca14b587047b8b3489f407a14a070") + scheme:add("urls", "https://github.com/ninja-build/ninja/archive/refs/tags/v$(version).tar.gz") + scheme:add("versions", "1.13.1", "f0055ad0369bf2e372955ba55128d000cfcc21777057806015b45e4accbebf23") end if add_schemes then @@ -101,21 +59,21 @@ package("cmake") if scheme_name and scheme_name == "binary" then raise("trigger failure when installing binaries, then we will fallback to install it from source tarball.") else - import("core.base.option") - os.vrunv("sh", {"./bootstrap", "--parallel=" .. (option.get("jobs") or tostring(os.default_njob())), - "--prefix=" .. package:installdir(), "--", "-DCMAKE_USE_OPENSSL=OFF"}) - import("package.tools.make").install(package) + local configs = {} + configs.version = package:version_str() + os.cp(path.join(package:scriptdir(), "port", "xmake.lua"), "xmake.lua") + import("package.tools.xmake").install(package, configs) end end) on_test(function (package) - os.vrun("cmake --version") + os.vrun("ninja --version") end) package_end() -add_requires("cmake", {system = false}) +add_requires("ninja", {system = false}) target("test") set_kind("binary") add_files("src/*.cpp") - add_packages("cmake") + add_packages("ninja") -- cgit v1.3.1 From a75179b440ba792bf9d3ea7c7dcd071cef18330c Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 9 Jan 2026 00:54:30 +0800 Subject: improve package tip --- .../action/require/impl/actions/install.lua | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 157424305..614820ebc 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -420,21 +420,26 @@ function _enable_ccache(package) end end +function _get_package_tipname(package) + local package_tipname = package:displayname() + local current_scheme = package:current_scheme() + if package:version_str() then + package_tipname = package_tipname .. " " .. package:version_str() + end + if current_scheme and not current_scheme:is_default() then + local scheme_name = current_scheme:name() + package_tipname = package_tipname .. " from " .. scheme_name + end + return package_tipname +end function main(package) - - -- enter working directory local oldir = _enter_workdir(package) - -- init tipname - local tipname = package:name() - if package:version_str() then - tipname = tipname .. "-" .. package:version_str() - end - -- install it local ok = true local oldenvs = os.getenvs() + local package_tipname = _get_package_tipname(package) try { function () @@ -498,7 +503,7 @@ function main(package) if option.get("verbose") or option.get("diagnosis") then print(fetchinfo) end - assert(fetchinfo, "fetch %s failed!", tipname) + assert(fetchinfo, "fetch %s failed!", package_tipname) -- this package is installed now if installed_now then @@ -520,7 +525,7 @@ function main(package) -- trace tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:displayname(), package:version_str() or "") + cprint("${yellow} => ${clear}install %s .. ${color.success}${text.success}", package_tipname) end, catch @@ -539,7 +544,7 @@ function main(package) -- trace tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:displayname(), package:version_str() or "") + cprint("${yellow} => ${clear}install %s .. ${color.failure}${text.failure}", package_tipname) -- leave the package environments os.setenvs(oldenvs) -- cgit v1.3.1 From b2829e1948636458f4e27b9ce85ae737f2c224d3 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 9 Jan 2026 22:57:49 +0800 Subject: improve current scheme --- xmake/core/package/package.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index b2b9d052e..9ca0a692f 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2306,6 +2306,12 @@ end -- get current scheme function _instance:current_scheme() + if self._CURRENT_SCHEME == nil then + local schemes_orderlist = self:schemes_orderlist() + if #schemes_orderlist > 0 then + self._CURRENT_SCHEME = schemes_orderlist[1] + end + end return self._CURRENT_SCHEME end @@ -2338,7 +2344,6 @@ function _instance:schemes_orderlist() table.insert(schemes_orderlist, scheme.new(name, {package = self})) end self._SCHEMES_ORDERLIST = schemes_orderlist - self._CURRENT_SCHEME = schemes_orderlist[1] end return schemes_orderlist end -- cgit v1.3.1 From c688e5681ff8f8e1b80e07fd78a528eacc4258b6 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 9 Jan 2026 23:24:13 +0800 Subject: fix mingw for ninja port --- tests/projects/package/schemes/port/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/package/schemes/port/xmake.lua b/tests/projects/package/schemes/port/xmake.lua index 7cf73fc43..1308c269c 100644 --- a/tests/projects/package/schemes/port/xmake.lua +++ b/tests/projects/package/schemes/port/xmake.lua @@ -32,7 +32,7 @@ target("libninja") add_files("src/version.cc") add_files("src/depfile_parser.cc", "src/lexer.cc") - if is_plat("windows") then + if is_plat("windows", "mingw") then add_files("src/subprocess-win32.cc") add_files("src/includes_normalize-win32.cc") add_files("src/msvc_helper-win32.cc") -- cgit v1.3.1 From 44290817fe9a5151253951004ab52a95ce625fe2 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 9 Jan 2026 23:32:58 +0800 Subject: fix mingw platform --- xmake/platforms/mingw/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/platforms/mingw/xmake.lua b/xmake/platforms/mingw/xmake.lua index 2abc1643a..0a3c51b65 100644 --- a/xmake/platforms/mingw/xmake.lua +++ b/xmake/platforms/mingw/xmake.lua @@ -31,7 +31,7 @@ platform("mingw") set_formats("binary", "$(name).exe") set_formats("symbol", "$(name).pdb") - set_toolchains("envs", "mingw", "yasm", "nasm", "fasm", "go") + set_toolchains("mingw", "yasm", "nasm", "fasm", "go") set_menu { config = -- cgit v1.3.1 From 429939bf538a9b30492908b617e4a2fd8e89e80c Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 9 Jan 2026 23:40:14 +0800 Subject: revert mingw platform --- xmake/platforms/mingw/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/platforms/mingw/xmake.lua b/xmake/platforms/mingw/xmake.lua index 0a3c51b65..2abc1643a 100644 --- a/xmake/platforms/mingw/xmake.lua +++ b/xmake/platforms/mingw/xmake.lua @@ -31,7 +31,7 @@ platform("mingw") set_formats("binary", "$(name).exe") set_formats("symbol", "$(name).pdb") - set_toolchains("mingw", "yasm", "nasm", "fasm", "go") + set_toolchains("envs", "mingw", "yasm", "nasm", "fasm", "go") set_menu { config = -- cgit v1.3.1 From 4542ea8937bcaa68eb3d3bfad3dd7fa1616cac4b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 00:28:25 +0800 Subject: fix ninja port --- tests/projects/package/schemes/port/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/package/schemes/port/xmake.lua b/tests/projects/package/schemes/port/xmake.lua index 1308c269c..92fb39f74 100644 --- a/tests/projects/package/schemes/port/xmake.lua +++ b/tests/projects/package/schemes/port/xmake.lua @@ -32,7 +32,7 @@ target("libninja") add_files("src/version.cc") add_files("src/depfile_parser.cc", "src/lexer.cc") - if is_plat("windows", "mingw") then + if is_plat("windows", "mingw", "msys") then add_files("src/subprocess-win32.cc") add_files("src/includes_normalize-win32.cc") add_files("src/msvc_helper-win32.cc") @@ -57,7 +57,7 @@ target("libninja") target:add("files", "src/jobserver.cc") target:add("files", "src/real_command_runner.cc") target:add("files", "src/status_printer.cc") - if target:is_plat("windows") then + if target:is_plat("windows", "mingw", "msys2") then target:add("files", "src/jobserver-win32.cc") else target:add("files", "src/jobserver-posix.cc") -- cgit v1.3.1 From e5a5d09e47bdc7e33f805b23634b9f7115eb1f36 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 00:37:49 +0800 Subject: rewrite precompile artifacts --- tests/projects/package/schemes/port/xmake.lua | 2 +- xmake/core/package/package.lua | 127 +++++++++------------ xmake/core/package/scheme.lua | 16 +++ .../action/require/impl/actions/install.lua | 3 + .../private/action/require/impl/package.lua | 2 +- xmake/modules/private/action/require/info.lua | 37 +++--- 6 files changed, 95 insertions(+), 92 deletions(-) diff --git a/tests/projects/package/schemes/port/xmake.lua b/tests/projects/package/schemes/port/xmake.lua index 92fb39f74..fe667a954 100644 --- a/tests/projects/package/schemes/port/xmake.lua +++ b/tests/projects/package/schemes/port/xmake.lua @@ -57,7 +57,7 @@ target("libninja") target:add("files", "src/jobserver.cc") target:add("files", "src/real_command_runner.cc") target:add("files", "src/status_printer.cc") - if target:is_plat("windows", "mingw", "msys2") then + if target:is_plat("windows", "mingw", "msys") then target:add("files", "src/jobserver-win32.cc") else target:add("files", "src/jobserver-posix.cc") diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 9ca0a692f..a21bf81bf 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -363,63 +363,62 @@ function _instance:url_http_headers(url) return self:current_scheme():url_http_headers(url) end --- set artifacts info -function _instance:artifacts_set(artifacts_info) - local versions = self:_versions_list() - if versions then - -- backup previous package configuration - self._ARTIFACTS_BACKUP = { - urls = table.copy(self:urls()), - versions = table.copy(versions), - install = self:script("install")} -- self:get() will get a table, it will be broken when call self:set() - - -- we switch to urls of the precompiled artifacts - self:urls_set(table.wrap(artifacts_info.urls)) - versions[self:version_str()] = artifacts_info.sha256 - self:set("install", function (package) - sandbox_module.import("lib.detect.find_path") - local rootdir = find_path("manifest.txt", path.join(os.curdir(), "*", "*", "*")) - if not rootdir then - os.raise("package(%s): manifest.txt not found when installing artifacts!", package:displayname()) - end - os.cp(path.join(rootdir, "*"), package:installdir(), {symlink = true}) - local manifest = package:manifest_load() - if not manifest then - os.raise("package(%s): load manifest.txt failed when installing artifacts!", package:displayname()) - end - if manifest.vars then - for k, v in pairs(manifest.vars) do - package:set(k, v) - end - end - if manifest.components then - local vars = manifest.components.vars - if vars then - for component_name, component_vars in pairs(vars) do - local comp = package:component(component_name) - if comp then - for k, v in pairs(component_vars) do - comp:set(k, v) - end +-- install the precompiled artifacts first +function _instance:use_precompiled_artifacts(artifacts_info) + + -- init the precompiled scheme + local precompiled_scheme = scheme.new("__precompiled__", {package = self}) + precompiled_scheme:urls_set(table.wrap(artifacts_info.urls)) + local versions_list = table.clone(self:_versions_list()) + versions_list[self:version_str()] = artifacts_info.sha256 + precompiled_scheme:_versions_list_set(versions_list) + + precompiled_scheme:set("install", function (package) + sandbox_module.import("lib.detect.find_path") + local rootdir = find_path("manifest.txt", path.join(os.curdir(), "*", "*", "*")) + if not rootdir then + os.raise("package(%s): manifest.txt not found when installing artifacts!", package:displayname()) + end + os.cp(path.join(rootdir, "*"), package:installdir(), {symlink = true}) + local manifest = package:manifest_load() + if not manifest then + os.raise("package(%s): load manifest.txt failed when installing artifacts!", package:displayname()) + end + if manifest.vars then + for k, v in pairs(manifest.vars) do + package:set(k, v) + end + end + if manifest.components then + local vars = manifest.components.vars + if vars then + for component_name, component_vars in pairs(vars) do + local comp = package:component(component_name) + if comp then + for k, v in pairs(component_vars) do + comp:set(k, v) end end end end - if manifest.envs then - local envs = self:_rawenvs() - for k, v in pairs(manifest.envs) do - envs[k] = v - end + end + if manifest.envs then + local envs = self:_rawenvs() + for k, v in pairs(manifest.envs) do + envs[k] = v end - -- save the remote install directory to fix the install path in .cmake/.pc files for precompiled artifacts - -- - -- @see https://github.com/xmake-io/xmake/issues/2210 - -- - manifest.artifacts = manifest.artifacts or {} - manifest.artifacts.remotedir = manifest.artifacts.installdir - end) - self._IS_PRECOMPILED = true - end + end + -- save the remote install directory to fix the install path in .cmake/.pc files for precompiled artifacts + -- + -- @see https://github.com/xmake-io/xmake/issues/2210 + -- + manifest.artifacts = manifest.artifacts or {} + manifest.artifacts.remotedir = manifest.artifacts.installdir + end) + + -- add the precompiled scheme + table.insert(self:schemes_orderlist(), 1, precompiled_scheme) + self:schemes()[precompiled_scheme:name()] = precompiled_scheme end -- is this package built? @@ -429,27 +428,7 @@ end -- is this package precompiled? function _instance:is_precompiled() - return self._IS_PRECOMPILED -end - --- fallback to source code build -function _instance:fallback_build() - if self:is_precompiled() then - local artifacts_backup = self._ARTIFACTS_BACKUP - if artifacts_backup then - if artifacts_backup.urls then - self:urls_set(artifacts_backup.urls) - end - if artifacts_backup.versions then - self._INFO:apival_set("versions", artifacts_backup.versions) - end - if artifacts_backup.install then - self._INFO:apival_set("install", artifacts_backup.install) - end - self._MANIFEST = nil - end - self._IS_PRECOMPILED = false - end + return self:current_scheme():is_precompiled() end -- get the given dependent package @@ -1772,7 +1751,7 @@ end function _instance:script(name, generic) -- get script - local script = self:get(name) + local script = self:current_scheme():get(name) or self:get(name) local result = select_script(script, {plat = self:plat(), arch = self:arch()}) or generic -- imports some modules first diff --git a/xmake/core/package/scheme.lua b/xmake/core/package/scheme.lua index 94a2a7d02..d03cce0a9 100644 --- a/xmake/core/package/scheme.lua +++ b/xmake/core/package/scheme.lua @@ -65,6 +65,11 @@ function _instance:is_default() return self:name() == "__default__" end +-- is precompiled scheme? +function _instance:is_precompiled() + return self:name() == "__precompiled__" +end + -- get the it's package function _instance:package() return self._PACKAGE @@ -211,6 +216,11 @@ function _instance:_versions_list() return self._VERSIONS_LIST end +-- set versions list +function _instance:_versions_list_set(versions_list) + self._VERSIONS_LIST = versions_list +end + -- get version function _instance:version() return self._VERSION @@ -397,6 +407,12 @@ function scheme.apis() -- scheme.add_xxx "scheme.add_urls" }, + script = { + -- scheme.on_xxx + "scheme.on_download" + , "scheme.on_install" + , "scheme.on_test" + }, keyvalues = { -- scheme.add_xxx "scheme.add_patches" diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 614820ebc..8a2514e1a 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -428,6 +428,9 @@ function _get_package_tipname(package) end if current_scheme and not current_scheme:is_default() then local scheme_name = current_scheme:name() + if current_scheme:is_precompiled() then + scheme_name = "the precompiled artifacts" + end package_tipname = package_tipname .. " from " .. scheme_name end return package_tipname diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 2c1cf98fb..017b45482 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -815,7 +815,7 @@ function _select_artifacts(package, artifacts_manifest) artifacts_info = _select_artifacts_for_generic(package, artifacts_manifest) end if artifacts_info then - package:artifacts_set(artifacts_info) + package:use_precompiled_artifacts(artifacts_info) end end diff --git a/xmake/modules/private/action/require/info.lua b/xmake/modules/private/action/require/info.lua index d065388d2..f1be7a01b 100644 --- a/xmake/modules/private/action/require/info.lua +++ b/xmake/modules/private/action/require/info.lua @@ -111,24 +111,29 @@ function main(requires_raw) -- show urls local urls = instance:urls() - if instance:is_precompiled() then - instance:fallback_build() - local urls_raw = instance:urls() - if urls_raw then - urls = table.join(urls, urls_raw) - end - end if urls and #urls > 0 then cprint(" -> ${color.dump.string_quote}urls${clear}:") - for _, url in ipairs(urls) do - print(" -> %s", filter.handle(url, instance)) - if git.asgiturl(url) then - local url_alias = instance:url_alias(url) - cprint(" -> ${yellow}%s", instance:revision(url_alias) or instance:tag() or instance:version_str()) - else - local sourcehash = instance:sourcehash(instance:url_alias(url)) - if sourcehash then - cprint(" -> ${yellow}%s", sourcehash) + local schemes = instance:schemes_orderlist() + if schemes then + for _, scheme in ipairs(schemes) do + if not scheme:is_precompiled() then + local urls = scheme:urls() + if urls and #urls > 0 then + local scheme_name = scheme:is_default() and "default" or scheme:name() + cprint(" -> ${magenta}%s${clear}:", scheme_name) + for _, url in ipairs(urls) do + print(" -> %s", filter.handle(url, instance)) + if git.asgiturl(url) then + local url_alias = scheme:url_alias(url) + cprint(" -> ${yellow}%s", scheme:revision(url_alias) or scheme:tag() or scheme:version_str()) + else + local sourcehash = scheme:sourcehash(scheme:url_alias(url)) + if sourcehash then + cprint(" -> ${yellow}%s", sourcehash) + end + end + end + end end end end -- cgit v1.3.1 From 441619bf075d1da9af183645aa738accc6cc8a19 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 00:42:53 +0800 Subject: fix use_precompiled_artifacts --- xmake/core/package/package.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index a21bf81bf..f1431f0ad 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -367,11 +367,17 @@ end function _instance:use_precompiled_artifacts(artifacts_info) -- init the precompiled scheme + local current_scheme = self:current_scheme() local precompiled_scheme = scheme.new("__precompiled__", {package = self}) precompiled_scheme:urls_set(table.wrap(artifacts_info.urls)) - local versions_list = table.clone(self:_versions_list()) + local versions_list = table.clone(current_scheme:_versions_list()) versions_list[self:version_str()] = artifacts_info.sha256 - precompiled_scheme:_versions_list_set(versions_list) + precompiled_scheme._VERSIONS_LIST = versions_list + precompiled_scheme._VERSION = current_scheme._VERSION + precompiled_scheme._VERSION_STR = current_scheme._VERSION_STR + precompiled_scheme._TAG = current_scheme._TAG + precompiled_scheme._COMMIT = current_scheme._COMMIT + precompiled_scheme._BRANCH = current_scheme._BRANCH precompiled_scheme:set("install", function (package) sandbox_module.import("lib.detect.find_path") @@ -419,6 +425,7 @@ function _instance:use_precompiled_artifacts(artifacts_info) -- add the precompiled scheme table.insert(self:schemes_orderlist(), 1, precompiled_scheme) self:schemes()[precompiled_scheme:name()] = precompiled_scheme + self._CURRENT_SCHEME = precompiled_scheme end -- is this package built? -- cgit v1.3.1 From e0d420311defad1f12af9619390c08a1a548f371 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 00:49:57 +0800 Subject: reset manifest --- xmake/core/package/package.lua | 8 ++++++++ xmake/modules/private/action/require/impl/install_packages.lua | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index f1431f0ad..b258c4e33 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -2334,6 +2334,14 @@ function _instance:schemes_orderlist() return schemes_orderlist end +-- prepare to install the given scheme +function _instance:prepare_install_scheme(scheme) + self:current_scheme_set(scheme) + + -- reset manifest to trigger reinstalling + self._MANIFEST = nil +end + -- generate lto configs function _instance:_generate_lto_configs(sourcekind) diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 1585c55cc..359f9ac47 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -497,7 +497,7 @@ function _do_install_packages(packages_install, packages_download, installdeps) -- install package from the multiple schemes for _, scheme in ipairs(instance:schemes_orderlist()) do - instance:current_scheme_set(scheme) + instance:prepare_install_scheme(scheme) -- download this package first local downloaded = true -- cgit v1.3.1 From 580464b9ea76a3d91e02be9ba836f2e906437109 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 00:50:50 +0800 Subject: improve tips --- xmake/modules/private/action/require/impl/actions/install.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 8a2514e1a..676bd8be5 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -429,9 +429,9 @@ function _get_package_tipname(package) if current_scheme and not current_scheme:is_default() then local scheme_name = current_scheme:name() if current_scheme:is_precompiled() then - scheme_name = "the precompiled artifacts" + scheme_name = "precompiled" end - package_tipname = package_tipname .. " from " .. scheme_name + package_tipname = package_tipname .. " ${dim}(" .. scheme_name .. ")${clear}" end return package_tipname end -- cgit v1.3.1 From 9351ccab49c7d470b70c35d74ae8a885ceae1658 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 13:18:20 +0800 Subject: fix format code --- tests/projects/package/schemes/port/xmake.lua | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/projects/package/schemes/port/xmake.lua b/tests/projects/package/schemes/port/xmake.lua index fe667a954..82f6978b9 100644 --- a/tests/projects/package/schemes/port/xmake.lua +++ b/tests/projects/package/schemes/port/xmake.lua @@ -12,37 +12,37 @@ target("libninja") set_kind("$(kind)") set_basename("ninja") - add_files("src/build_log.cc") - add_files("src/build.cc") - add_files("src/clean.cc") - add_files("src/clparser.cc") - add_files("src/debug_flags.cc") - add_files("src/deps_log.cc") - add_files("src/disk_interface.cc") - add_files("src/edit_distance.cc") - add_files("src/eval_env.cc") - add_files("src/graph.cc") - add_files("src/graphviz.cc") - add_files("src/line_printer.cc") - add_files("src/manifest_parser.cc") - add_files("src/metrics.cc") - add_files("src/state.cc") - add_files("src/string_piece_util.cc") - add_files("src/util.cc") - add_files("src/version.cc") + add_files("src/build_log.cc") + add_files("src/build.cc") + add_files("src/clean.cc") + add_files("src/clparser.cc") + add_files("src/debug_flags.cc") + add_files("src/deps_log.cc") + add_files("src/disk_interface.cc") + add_files("src/edit_distance.cc") + add_files("src/eval_env.cc") + add_files("src/graph.cc") + add_files("src/graphviz.cc") + add_files("src/line_printer.cc") + add_files("src/manifest_parser.cc") + add_files("src/metrics.cc") + add_files("src/state.cc") + add_files("src/string_piece_util.cc") + add_files("src/util.cc") + add_files("src/version.cc") add_files("src/depfile_parser.cc", "src/lexer.cc") if is_plat("windows", "mingw", "msys") then - add_files("src/subprocess-win32.cc") - add_files("src/includes_normalize-win32.cc") - add_files("src/msvc_helper-win32.cc") - add_files("src/msvc_helper_main-win32.cc") - add_files("src/getopt.c", {sourcekind = "cxx"}) - add_files("src/minidump-win32.cc") + add_files("src/subprocess-win32.cc") + add_files("src/includes_normalize-win32.cc") + add_files("src/msvc_helper-win32.cc") + add_files("src/msvc_helper_main-win32.cc") + add_files("src/getopt.c", {sourcekind = "cxx"}) + add_files("src/minidump-win32.cc") add_defines("NOMINMAX") else - add_files("src/subprocess-posix.cc") + add_files("src/subprocess-posix.cc") end if is_plat("mingw") then @@ -58,7 +58,7 @@ target("libninja") target:add("files", "src/real_command_runner.cc") target:add("files", "src/status_printer.cc") if target:is_plat("windows", "mingw", "msys") then - target:add("files", "src/jobserver-win32.cc") + target:add("files", "src/jobserver-win32.cc") else target:add("files", "src/jobserver-posix.cc") end @@ -67,8 +67,8 @@ target("libninja") if version:lt("1.13.1") then target:add("files", "src/status.cc") end - target:add("files", "src/json.cc") - target:add("files", "src/missing_deps.cc") + target:add("files", "src/json.cc") + target:add("files", "src/missing_deps.cc") end if version:ge("1.10.0") then target:add("files", "src/dyndep.cc") -- cgit v1.3.1 From bb14ec35f33aa77bc4cb88a61ebe27225cfb86ba Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 21:13:04 +0800 Subject: improve scheme tips --- xmake/modules/private/action/require/impl/package.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 017b45482..6e97a3452 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -411,7 +411,10 @@ function _select_package_version(package, requireinfo, locked_requireinfo) if scheme_version then scheme:version_set(scheme_version, scheme_source) if version then - assert(scheme_version == version, "package(%s): the version lists of schemes are mismatch.") + if scheme_version ~= version then + raise("package(%s): the version lists of schemes are mismatch.\n -> scheme(%s): %s not found!", + package:name(), scheme:name(), version) + end else version = scheme_version source = scheme_source -- cgit v1.3.1 From 705c56d45cc92d4aeebc95964347fa548d76ba4e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 21:18:46 +0800 Subject: fix scheme test --- tests/projects/package/schemes/xmake.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/projects/package/schemes/xmake.lua b/tests/projects/package/schemes/xmake.lua index 689b9c88d..16fad87fa 100644 --- a/tests/projects/package/schemes/xmake.lua +++ b/tests/projects/package/schemes/xmake.lua @@ -54,8 +54,7 @@ package("ninja") end on_install("@linux", "@windows", "@msys", "@cygwin", "@macosx", function (package) - local scheme = package:current_scheme() - local scheme_name = scheme and scheme:name() or package:data("scheme") + local scheme_name = package.current_scheme and package:current_scheme():name() or package:data("scheme") if scheme_name and scheme_name == "binary" then raise("trigger failure when installing binaries, then we will fallback to install it from source tarball.") else -- cgit v1.3.1 From 0cdef1cae501f1f023ea77fafefa1463b82590e0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 22:05:16 +0800 Subject: improve to select scheme version --- xmake/modules/private/action/require/impl/package.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 6e97a3452..8b0f5dc1b 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -405,8 +405,7 @@ function _select_package_version(package, requireinfo, locked_requireinfo) -- select version from schemes local version, source - local schemes = package:schemes_orderlist() - for _, scheme in ipairs(schemes) do + table.remove_if(package:schemes_orderlist(), function (i, scheme) local scheme_version, scheme_source = _select_version_from_scheme(scheme, requireinfo) if scheme_version then scheme:version_set(scheme_version, scheme_source) @@ -419,8 +418,12 @@ function _select_package_version(package, requireinfo, locked_requireinfo) version = scheme_version source = scheme_source end + else + -- remove this scheme if version is not matched + package:schemes()[scheme:name()] = nil + return true end - end + end) if not version and not package:is_thirdparty() and is_system ~= true then raise("package(%s): version(%s) not found!", package:name(), require_version) @@ -971,7 +974,6 @@ function _load_package(packagename, requireinfo, opt) -- select package version local version, source = _select_package_version(package, requireinfo, locked_requireinfo) if version then - package:version_set(version, source) package:data_set("__locked_requireinfo", locked_requireinfo) end -- cgit v1.3.1 From de1004a3930a91057debe62b06757bb8aad7faaf Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 22:09:41 +0800 Subject: fix current scheme --- xmake/modules/private/action/require/impl/package.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 8b0f5dc1b..941fca7fe 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -421,6 +421,8 @@ function _select_package_version(package, requireinfo, locked_requireinfo) else -- remove this scheme if version is not matched package:schemes()[scheme:name()] = nil + -- reset current scheme cache, we need to resolve new current scheme + package:current_scheme_set(nil) return true end end) -- cgit v1.3.1 From b84340552514434dbd213354a98a653bdd7d0d60 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 10 Jan 2026 23:14:45 +0800 Subject: fix lock version --- xmake/modules/private/action/require/impl/package.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 941fca7fe..2d44238db 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -400,6 +400,7 @@ function _select_package_version(package, requireinfo, locked_requireinfo) elseif locked_requireinfo.tag then source = "tag" end + package:version_set(version, source) return version, source end -- cgit v1.3.1