diff options
| author | ruki <[email protected]> | 2025-09-29 22:10:21 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-09-29 22:10:21 +0800 |
| commit | 25c60fd7db271e2f59bae730366867b7d648684f (patch) | |
| tree | 7200b0f2d17cd7494db3935de9a8d0e5012f5632 | |
| parent | 87451e315f744dff0bd953cdfb72ca7ff1451835 (diff) | |
| parent | 4d0f2e29c75179d2efd4f5536821f8212556411c (diff) | |
Merge pull request #6850 from Shiffted/check_package_api
add package api checking
| -rw-r--r-- | xmake/actions/build/check.lua | 24 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/check_api.lua | 32 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/package.lua | 3 | ||||
| -rw-r--r-- | xmake/modules/private/check/checker.lua | 2 | ||||
| -rw-r--r-- | xmake/modules/private/check/checkers/api/api_checker.lua | 87 | ||||
| -rw-r--r-- | xmake/modules/private/check/checkers/api/package/kind.lua | 42 | ||||
| -rw-r--r-- | xmake/modules/private/check/show.lua | 40 |
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 |
