summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-12-04 13:48:01 +0800
committerGitHub <[email protected]>2024-12-04 13:48:01 +0800
commitded88ac6e855f8d1bb07657766ec249688cb526a (patch)
tree825580a1918d754e0f34bccb4dffd57472c1fcb4
parent6c09c81a3fa14619459168f0fe814431011d4cc8 (diff)
parentcd93b9aa6fd61bccc5b91bf6a3e01b8d00e4a106 (diff)
Merge pull request #5923 from xmake-io/deps
Solve the package configs conflict
-rw-r--r--.github/workflows/macos.yml2
-rw-r--r--tests/projects/package/compatibility/deps_with_version/xmake.lua5
-rwxr-xr-xtests/projects/package/compatibility/sync_requires_to_deps/src/main.c6
-rw-r--r--tests/projects/package/compatibility/sync_requires_to_deps/test.lua10
-rw-r--r--tests/projects/package/compatibility/sync_requires_to_deps/xmake.lua33
-rw-r--r--xmake/core/project/policy.lua8
-rw-r--r--xmake/core/project/project.lua36
-rw-r--r--xmake/modules/private/action/require/impl/package.lua118
8 files changed, 187 insertions, 31 deletions
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index f6129fbfd..623d1f858 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
- os: [macos-12]
+ os: [macos-13]
arch: [x86_64]
runs-on: ${{ matrix.os }}
diff --git a/tests/projects/package/compatibility/deps_with_version/xmake.lua b/tests/projects/package/compatibility/deps_with_version/xmake.lua
index 1ceb5f3a1..9f9d49e29 100644
--- a/tests/projects/package/compatibility/deps_with_version/xmake.lua
+++ b/tests/projects/package/compatibility/deps_with_version/xmake.lua
@@ -7,14 +7,14 @@ package_end()
package("bar")
add_deps("zlib 1.2.x")
-- add_deps("libpng dev")
--- add_deps("libpng", {configs = {debug = true}})
+-- add_deps("boost", {system = false, configs = {zlib = false}})
set_policy("package.install_locally", true)
on_install(function () end)
package_end()
package("zoo")
-- add_deps("libpng master")
--- add_deps("libpng", {configs = {shared = true}})
+-- add_deps("boost", {system = false, configs = {zlib = true}})
set_policy("package.install_locally", true)
on_install(function () end)
package_end()
@@ -26,6 +26,7 @@ package("test")
package_end()
add_requires("test")
+--add_requireconfs("**.boost", {override = true, configs = {zlib = false}})
target("test")
set_kind("binary")
diff --git a/tests/projects/package/compatibility/sync_requires_to_deps/src/main.c b/tests/projects/package/compatibility/sync_requires_to_deps/src/main.c
new file mode 100755
index 000000000..113930e1a
--- /dev/null
+++ b/tests/projects/package/compatibility/sync_requires_to_deps/src/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+ printf("hello world!\n");
+ return 0;
+}
diff --git a/tests/projects/package/compatibility/sync_requires_to_deps/test.lua b/tests/projects/package/compatibility/sync_requires_to_deps/test.lua
new file mode 100644
index 000000000..a6690754b
--- /dev/null
+++ b/tests/projects/package/compatibility/sync_requires_to_deps/test.lua
@@ -0,0 +1,10 @@
+function main(t)
+ -- freebsd ci is slower
+ if is_host("bsd") 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/compatibility/sync_requires_to_deps/xmake.lua b/tests/projects/package/compatibility/sync_requires_to_deps/xmake.lua
new file mode 100644
index 000000000..439e322e9
--- /dev/null
+++ b/tests/projects/package/compatibility/sync_requires_to_deps/xmake.lua
@@ -0,0 +1,33 @@
+
+package("foo")
+ add_deps("zlib >=1.2.13")
+ set_policy("package.install_locally", true)
+ on_install(function () end)
+package_end()
+
+package("bar")
+ add_deps("zlib 1.2.x")
+ set_policy("package.install_locally", true)
+ on_install(function () end)
+package_end()
+
+package("zoo")
+ set_policy("package.install_locally", true)
+ on_install(function () end)
+package_end()
+
+package("test")
+ add_deps("foo", "bar", "zoo")
+ set_policy("package.install_locally", true)
+ on_install(function () end)
+package_end()
+
+set_policy("package.sync_requires_to_deps", true)
+
+add_requires("test")
+add_requires("zlib >=1.2.13", {system = false, configs = {shared = true}})
+
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+ add_packages("test")
diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua
index 3f7915b84..46b16e256 100644
--- a/xmake/core/project/policy.lua
+++ b/xmake/core/project/policy.lua
@@ -136,8 +136,14 @@ function policy.policies()
-- if true, then any updates to library dependencies, such as buildhash changes due to version changes,
-- will force the installed packages to be recompiled and installed. @see https://github.com/xmake-io/xmake/issues/2719
["package.librarydeps.strict_compatibility"] = {description = "Set strict compatibility for package and it's all library dependencies.", type = "boolean"},
+ -- Resolve package dependencies conflict automatically
+ -- @see https://github.com/xmake-io/xmake/issues/5745
+ ["package.resolve_depconflict"] = {description = "Automatically resolve package dependencies conflict.", default = true, type = "boolean"},
+ -- Synchronize add_requires configuration in toplevel to all package dependencies for this package
+ -- @see https://github.com/xmake-io/xmake/issues/5745
+ ["package.sync_requires_to_deps"] = {description = "Synchronize requires configuration to all package dependencies.", default = false, type = "boolean"},
-- Automatically passes dependency configuration for inner xmake package
- -- https://github.com/xmake-io/xmake/issues/3952
+ -- @see https://github.com/xmake-io/xmake/issues/3952
["package.xmake.pass_depconfs"] = {description = "Automatically passes dependency configuration for inner xmake package", default = true, type = "boolean"},
-- It will force cmake package use ninja for build
["package.cmake_generator.ninja"] = {description = "Set cmake package use ninja for build", type = "boolean"},
diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua
index 6c896dde5..77793d3e5 100644
--- a/xmake/core/project/project.lua
+++ b/xmake/core/project/project.lua
@@ -1030,6 +1030,42 @@ function project.requireconfs_str()
project.requires_str()
local requireconfs_str = project._memcache():get("requireconfs_str")
local requireconfs_extra = project._memcache():get("requireconfs_extra")
+ -- synchronize requires configuration to all package dependencies.
+ -- @see https://github.com/xmake-io/xmake/issues/5745#issuecomment-2513951471
+ if project.policy("package.sync_requires_to_deps") then
+ local requires_str = project._memcache():get("requires_str")
+ local requires_extra = project._memcache():get("requires_extra")
+ local sync_requires_to_deps = project._memcache():get("package.sync_requires_to_deps")
+ if requires_str and not sync_requires_to_deps then
+ requires_extra = requires_extra and table.wrap(requires_extra) or {}
+ requireconfs_str = requireconfs_str and table.wrap(requireconfs_str) or {}
+ requireconfs_extra = requireconfs_extra and table.wrap(requireconfs_extra) or {}
+ for _, require_str in ipairs(table.wrap(requires_str)) do
+ if not require_str:find("::", 1, true) then
+ local splitinfo = require_str:split("%s")
+ local packagename = splitinfo[1]
+ local packageversion = splitinfo[2]
+ local requireconf_str = "**." .. packagename
+ local requireconf_extra = table.clone(requires_extra[require_str])
+ if requireconf_extra then
+ requireconf_extra.configs = table.clone(requireconf_extra.configs) or {}
+ end
+ if packageversion then
+ requireconf_extra = requireconf_extra or {configs = {}}
+ requireconf_extra.configs.version = packageversion
+ end
+ if requireconf_extra then
+ requireconf_extra.override = true
+ table.insert(requireconfs_str, requireconf_str)
+ requireconfs_extra[requireconf_str] = requireconf_extra
+ end
+ end
+ end
+ project._memcache():set("requireconfs_str", requireconfs_str)
+ project._memcache():set("requireconfs_extra", requireconfs_extra)
+ project._memcache():set("package.sync_requires_to_deps", true)
+ end
+ end
return requireconfs_str, requireconfs_extra
end
diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua
index 100a24560..30c571592 100644
--- a/xmake/modules/private/action/require/impl/package.lua
+++ b/xmake/modules/private/action/require/impl/package.lua
@@ -183,6 +183,26 @@ function _load_require(require_str, requires_extra, opt)
end
end
+ -- resolve require info
+ local resolvedinfo = opt.resolvedinfo
+ local requirepath = opt.requirepath
+ if requirepath then
+ requirepath = requirepath .. "." .. packagename
+ else
+ requirepath = packagename
+ end
+ resolvedinfo = resolvedinfo and resolvedinfo[requirepath]
+ if resolvedinfo then
+ -- resolve the conflict package version
+ if resolvedinfo.version then
+ version = resolvedinfo.version
+ end
+ -- resolve the conflict package configs
+ if resolvedinfo.configs then
+ require_extra.configs = resolvedinfo.configs
+ end
+ end
+
-- get required building configurations
-- we need to clone a new configs object, because the whole requireinfo will be modified later.
-- @see https://github.com/xmake-io/xmake-repo/pull/2067
@@ -216,22 +236,6 @@ function _load_require(require_str, requires_extra, opt)
require_extra.system = false
end
- -- resolve require info
- local resolvedinfo = opt.resolvedinfo
- local requirepath = opt.requirepath
- if requirepath then
- requirepath = requirepath .. "." .. packagename
- else
- requirepath = packagename
- end
- resolvedinfo = resolvedinfo and resolvedinfo[requirepath]
- if resolvedinfo then
- -- resolve the conflict package version
- if resolvedinfo.version then
- version = resolvedinfo.version
- end
- end
-
-- init required item
local required = {}
local parentinfo = opt.parentinfo
@@ -257,7 +261,8 @@ function _load_require(require_str, requires_extra, opt)
verify = require_extra.verify, -- default: true, we can set false to ignore sha256sum and select any version
external = require_extra.external, -- default: true, we use sysincludedirs/-isystem instead of -I/xxx
private = require_extra.private, -- default: false, private package, only for installation, do not export any links/includes and environments
- build = require_extra.build -- default: false, always build packages, we do not use the precompiled artifacts
+ build = require_extra.build, -- default: false, always build packages, we do not use the precompiled artifacts
+ resolvedinfo = resolvedinfo -- the resolved info for the conflict version/configs
}
return required.packagename, required.requireinfo
end
@@ -1206,29 +1211,44 @@ function _get_requirepaths(package)
table.insert(requirepaths, requirepath .. "." .. package:name())
end
end
+ -- we also need to resolve requires conflict in toplevel, if `package.sync_requires_to_deps` policy is enabled.
+ -- @see https://github.com/xmake-io/xmake/issues/5745#issuecomment-2513951471
+ if project.policy("package.sync_requires_to_deps") then
+ table.insert(requirepaths, package:name())
+ end
else
table.insert(requirepaths, package:name())
end
return requirepaths
end
--- get configs key for compatibility
+-- get compatibility key
function _get_package_compatkey(dep)
local key = dep:plat() .. "/" .. dep:arch() .. "/" .. (dep:kind() or "")
if dep:is_system() then
key = key .. "/system"
end
- local configs = dep:requireinfo().configs
- if configs then
- local configs_order = {}
- for k, v in pairs(configs) do
- if type(v) == "table" then
- v = string.serialize(v, {strip = true, indent = false, orderkeys = true})
+ local resolve_depconflict = project.policy("package.resolve_depconflict")
+ if resolve_depconflict == nil then
+ resolve_depconflict = dep:policy("package.resolve_depconflict")
+ end
+ if resolve_depconflict == false then
+ if dep:version_str() then
+ key = key .. "/" .. dep:version_str()
+ end
+ local configs = dep:requireinfo().configs
+ if configs then
+ local configs_order = {}
+ for k, v in pairs(configs) do
+ if type(v) == "table" then
+ v = string.serialize(v, {strip = true, indent = false, orderkeys = true})
+ end
+ table.insert(configs_order, k .. "=" .. tostring(v))
end
- table.insert(configs_order, k .. "=" .. tostring(v))
+ table.sort(configs_order)
+ key = key .. ":" .. string.serialize(configs_order, true)
end
- table.sort(configs_order)
- key = key .. ":" .. string.serialize(configs_order, true)
+
end
return key
end
@@ -1298,16 +1318,42 @@ function _check_and_resolve_package_depconflicts_impl(package, name, deps, resol
-- check configs compatibility
local prevkey
+ local configs
local configs_conflict = false
for _, dep in ipairs(deps) do
local key = _get_package_compatkey(dep)
if prevkey then
if prevkey ~= key then
configs_conflict = true
+ break
end
else
prevkey = key
end
+ local depconfigs = dep:requireinfo().configs
+ if configs and depconfigs then
+ for k, v in pairs(depconfigs) do
+ local oldv = configs[k]
+ if oldv ~= nil then
+ local v_key = tostring(v)
+ local oldv_key = tostring(oldv)
+ if type(v) == "table" then
+ v_key = string.serialize(v, {strip = true, indent = false, orderkeys = true})
+ end
+ if type(oldv) == "table" then
+ oldv_key = string.serialize(oldv, {strip = true, indent = false, orderkeys = true})
+ end
+ if v_key ~= oldv_key then
+ configs_conflict = true
+ break
+ end
+ else
+ configs[k] = v
+ end
+ end
+ else
+ configs = depconfigs
+ end
end
if configs_conflict then
print("package(%s): add_deps(%s, ...)", package:name(), name)
@@ -1335,6 +1381,16 @@ function _check_and_resolve_package_depconflicts_impl(package, name, deps, resol
end
end
end
+
+ -- resolve configs
+ if configs then
+ for _, dep in ipairs(deps) do
+ for _, requirepath in ipairs(_get_requirepaths(dep)) do
+ resolvedinfo[requirepath] = resolvedinfo[requirepath] or {}
+ resolvedinfo[requirepath].configs = configs
+ end
+ end
+ end
end
-- check and resolve dependencies conflicts
@@ -1573,11 +1629,19 @@ function get_configs_str(package)
if parents_str then
table.insert(configs, "from:" .. parents_str)
end
+ local license = package:get("license")
+ if license then
+ table.insert(configs, "license:" .. license)
+ end
local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or ""
local limitwidth = math.floor(os.getwinsize().width * 2 / 3)
if #configs_str > limitwidth then
configs_str = configs_str:sub(1, limitwidth) .. " ..)"
end
+ local resolvedinfo = requireinfo.resolvedinfo
+ if resolvedinfo then
+ configs_str = configs_str .. " " .. "${color.warning}(conflict resolved)${clear}"
+ end
return configs_str
end