summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-09-29 22:10:21 +0800
committerGitHub <[email protected]>2025-09-29 22:10:21 +0800
commit25c60fd7db271e2f59bae730366867b7d648684f (patch)
tree7200b0f2d17cd7494db3935de9a8d0e5012f5632
parent87451e315f744dff0bd953cdfb72ca7ff1451835 (diff)
parent4d0f2e29c75179d2efd4f5536821f8212556411c (diff)
Merge pull request #6850 from Shiffted/check_package_api
add package api checking
-rw-r--r--xmake/actions/build/check.lua24
-rw-r--r--xmake/modules/private/action/require/impl/check_api.lua32
-rw-r--r--xmake/modules/private/action/require/impl/package.lua3
-rw-r--r--xmake/modules/private/check/checker.lua2
-rw-r--r--xmake/modules/private/check/checkers/api/api_checker.lua87
-rw-r--r--xmake/modules/private/check/checkers/api/package/kind.lua42
-rw-r--r--xmake/modules/private/check/show.lua40
7 files changed, 179 insertions, 51 deletions
diff --git a/xmake/actions/build/check.lua b/xmake/actions/build/check.lua
index 24f13e2f8..2ec3ebc85 100644
--- a/xmake/actions/build/check.lua
+++ b/xmake/actions/build/check.lua
@@ -22,27 +22,7 @@
import("core.base.option")
import("core.project.project")
import("private.check.checker")
-
-function _show(str, opt)
- opt = opt or {}
- _g.showed = _g.showed or {}
- local showed = _g.showed
- local infostr
- if str and opt.sourcetips then
- infostr = string.format("%s${clear}: %s", opt.sourcetips, str)
- elseif opt.sourcetips and opt.apiname and opt.value ~= nil then
- infostr = string.format("%s${clear}: unknown %s value '%s'", opt.sourcetips, opt.apiname, opt.value)
- elseif str then
- infostr = string.format("${clear}: %s", str)
- end
- if opt.probable_value then
- infostr = string.format("%s, it may be '%s'", infostr, opt.probable_value)
- end
- if not showed[infostr] then
- wprint(infostr)
- showed[infostr] = true
- end
-end
+import("private.check.show")
function main(targetnames, opt)
opt = opt or {}
@@ -70,7 +50,7 @@ function main(targetnames, opt)
if (info.build and opt.build) or (info.build_failure and opt.build_failure) then
local check = import("private.check.checkers." .. name, {anonymous = true})
for _, target in ipairs(targets) do
- check({target = target, show = _show})
+ check({target = target, show = show.wshow})
end
end
end
diff --git a/xmake/modules/private/action/require/impl/check_api.lua b/xmake/modules/private/action/require/impl/check_api.lua
new file mode 100644
index 000000000..7fd5459c1
--- /dev/null
+++ b/xmake/modules/private/action/require/impl/check_api.lua
@@ -0,0 +1,32 @@
+--!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 Shiffted
+-- @file check_api.lua
+--
+
+import("private.check.checker")
+import("private.check.show")
+
+function main(package)
+ local checkers = checker.checkers()
+ for name, info in table.orderpairs(checkers) do
+ if info.load then
+ local check = import("private.check.checkers." .. name, {anonymous = true})
+ check({package = package, show = show.wshow})
+ end
+ end
+end
diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua
index a81ba6f99..11b06d381 100644
--- a/xmake/modules/private/action/require/impl/package.lua
+++ b/xmake/modules/private/action/require/impl/package.lua
@@ -31,6 +31,7 @@ import("core.tool.toolchain")
import("core.platform.platform")
import("core.package.package", {alias = "core_package"})
import("devel.git")
+import("private.action.require.impl.check_api")
import("private.action.require.impl.repository")
import("private.action.require.impl.search_packages")
import("private.action.require.impl.utils.requirekey", {alias = "_get_requirekey"})
@@ -1128,6 +1129,8 @@ function _load_package(packagename, requireinfo, opt)
-- load environments from the manifest to enable the environments of on_install()
package:envs_load()
+ check_api(package)
+
-- save this package package to cache
_memcache():set2("packages", packagekey, package)
diff --git a/xmake/modules/private/check/checker.lua b/xmake/modules/private/check/checker.lua
index 8080b608d..923c35809 100644
--- a/xmake/modules/private/check/checker.lua
+++ b/xmake/modules/private/check/checker.lua
@@ -26,6 +26,8 @@ function checkers()
local checkers = _g._CHECKERS
if not checkers then
checkers = {
+ -- package api checkers
+ ["api.package.kind"] = {description = "Check kind configuration in package.", load = true},
-- target api checkers
["api.target.version"] = {description = "Check version configuration in target."},
["api.target.kind"] = {description = "Check kind configuration in target.", build = true},
diff --git a/xmake/modules/private/check/checkers/api/api_checker.lua b/xmake/modules/private/check/checkers/api/api_checker.lua
index 805030421..10e3942ac 100644
--- a/xmake/modules/private/check/checkers/api/api_checker.lua
+++ b/xmake/modules/private/check/checkers/api/api_checker.lua
@@ -21,10 +21,28 @@
-- imports
import("core.base.option")
import("core.base.hashset")
+import("core.package.package")
import("core.project.project")
import("private.check.checker")
import("private.utils.target", {alias = "target_utils"})
+function _get_project_packages()
+ local project_packages = _g.project_packages
+ if not project_packages then
+ project_packages = {}
+ for name, _ in pairs(project.required_packages()) do
+ local pkg, errors = package.load_from_project(name)
+ if pkg then
+ table.insert(project_packages, pkg)
+ elseif errors then
+ raise(errors)
+ end
+ end
+ _g.project_packages = project_packages
+ end
+ return project_packages
+end
+
-- get the most probable value
function _get_most_probable_value(value, valueset)
local result
@@ -59,7 +77,7 @@ function _do_show(str, opt)
end
-- show result
-function _show(apiname, value, target, opt)
+function _show(apiname, value, instance, opt)
opt = opt or {}
-- match level? verbose: note/warning/error, default: warning/error
@@ -69,13 +87,13 @@ function _show(apiname, value, target, opt)
end
-- get source information
- local sourceinfo = target:sourceinfo(apiname, value) or {}
+ local sourceinfo = instance:sourceinfo(apiname, value) or {}
local sourcetips = sourceinfo.file or ""
if sourceinfo.line then
sourcetips = sourcetips .. ":" .. (sourceinfo.line or -1)
end
if #sourcetips == 0 then
- sourcetips = string.format("target(%s)", target:name())
+ sourcetips = string.format("%s(%s)", instance:type(), instance:name())
end
-- get level tips
@@ -105,21 +123,21 @@ function _show(apiname, value, target, opt)
probable_value = probable_value})
end
--- check target
-function _check_target(target, apiname, valueset, level, opt)
- local target_valueset = valueset
+-- check instance
+function _check_instance(instance, apiname, valueset, level, opt)
+ local instance_valueset = valueset
if type(opt.values) == "function" then
- local target_values = opt.values(target)
- if target_values then
- target_valueset = hashset.from(target_values)
+ local instance_values = opt.values(instance)
+ if instance_values then
+ instance_valueset = hashset.from(instance_values)
end
end
- local values = target:get(apiname)
+ local values = instance:get(apiname)
for _, value in ipairs(values) do
if opt.check then
- local ok, errors = opt.check(target, value)
+ local ok, errors = opt.check(instance, value)
if not ok then
- local reported = _show(apiname, value, target, {
+ local reported = _show(apiname, value, instance, {
show = opt.show,
showstr = errors,
level = level})
@@ -127,10 +145,10 @@ function _check_target(target, apiname, valueset, level, opt)
checker.update_stats(level)
end
end
- elseif not target_valueset:has(value) then
- local reported = _show(apiname, value, target, {
+ elseif not instance_valueset:has(value) then
+ local reported = _show(apiname, value, instance, {
show = opt.show,
- valueset = target_valueset,
+ valueset = instance_valueset,
level = level})
if reported then
checker.update_stats(level)
@@ -139,6 +157,24 @@ function _check_target(target, apiname, valueset, level, opt)
end
end
+-- check api configuration in instances
+function _check_instances(apiname, instance, instances_func, opt)
+ local level = opt.level or "warning"
+ local valueset
+ if opt.values and type(opt.values) ~= "function" then
+ valueset = hashset.from(opt.values)
+ else
+ valueset = hashset.new()
+ end
+ if instance then
+ _check_instance(instance, apiname, valueset, level, opt)
+ else
+ for _, instance in pairs(instances_func()) do
+ _check_instance(instance, apiname, valueset, level, opt)
+ end
+ end
+end
+
-- check flag
-- @see https://github.com/xmake-io/xmake/issues/3594
function check_flag(target, toolinst, flagkind, flag)
@@ -156,18 +192,11 @@ end
-- check api configuration in targets
function check_targets(apiname, opt)
opt = opt or {}
- local level = opt.level or "warning"
- local valueset
- if opt.values and type(opt.values) ~= "function" then
- valueset = hashset.from(opt.values)
- else
- valueset = hashset.new()
- end
- if opt.target then
- _check_target(opt.target, apiname, valueset, level, opt)
- else
- for _, target in pairs(project.targets()) do
- _check_target(target, apiname, valueset, level, opt)
- end
- end
+ _check_instances(apiname, opt.target, project.targets, opt)
+end
+
+-- check api configuration in packages
+function check_packages(apiname, opt)
+ opt = opt or {}
+ _check_instances(apiname, opt.package, _get_project_packages, opt)
end
diff --git a/xmake/modules/private/check/checkers/api/package/kind.lua b/xmake/modules/private/check/checkers/api/package/kind.lua
new file mode 100644
index 000000000..4a9c309e3
--- /dev/null
+++ b/xmake/modules/private/check/checkers/api/package/kind.lua
@@ -0,0 +1,42 @@
+--!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 Shiffted
+-- @file kind.lua
+--
+
+import(".api_checker")
+
+function main(opt)
+ opt = opt or {}
+ api_checker.check_packages("kind", table.join(opt, {check = function(package, value)
+ if value == "library" then
+ local extraconf = package:extraconf("kind", "library")
+ if extraconf then
+ if extraconf.headeronly and extraconf.moduleonly then
+ return false, "a library package cannot be set as both 'headeronly' and 'moduleonly'"
+ end
+ for key, _ in pairs(extraconf) do
+ if key ~= "headeronly" and key ~= "moduleonly" then
+ return false, string.format("unknown kind configuration '%s'", key)
+ end
+ end
+ end
+ return true
+ end
+ return value == "binary" or value == "toolchain" or value == "template"
+ end}))
+end
diff --git a/xmake/modules/private/check/show.lua b/xmake/modules/private/check/show.lua
new file mode 100644
index 000000000..4d94a7c5e
--- /dev/null
+++ b/xmake/modules/private/check/show.lua
@@ -0,0 +1,40 @@
+--!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 Shiffted
+-- @file show.lua
+--
+
+function wshow(str, opt)
+ opt = opt or {}
+ _g.showed = _g.showed or {}
+ local showed = _g.showed
+ local infostr
+ if str and opt.sourcetips then
+ infostr = string.format("%s${clear}: %s", opt.sourcetips, str)
+ elseif opt.sourcetips and opt.apiname and opt.value ~= nil then
+ infostr = string.format("%s${clear}: unknown %s value '%s'", opt.sourcetips, opt.apiname, opt.value)
+ elseif str then
+ infostr = string.format("${clear}: %s", str)
+ end
+ if opt.probable_value then
+ infostr = string.format("%s, it may be '%s'", infostr, opt.probable_value)
+ end
+ if not showed[infostr] then
+ wprint(infostr)
+ showed[infostr] = true
+ end
+end