From deaf196c40c2a7a6dcb7fe2b3917a79c28c99a66 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Mar 2026 23:23:44 +0800 Subject: improve vcpkg/find_package --- xmake/modules/package/manager/vcpkg/find_package.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 045adf050..531137b29 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -136,6 +136,13 @@ function _find_package(vcpkg, vcpkgdir, name, opt) -- get configs local configs = opt.configs or {} + -- extract required features before stripping, e.g. curl[openssl,mbedtls] -> {"openssl", "mbedtls"} + local required_features + local features_str = name:match("%[(.-)%]") + if features_str then + required_features = features_str:split(",", {plain = true}) + end + -- fix name, e.g. ffmpeg[x264] as ffmpeg -- @see https://github.com/xmake-io/xmake/issues/925 name = name:gsub("%[.-%]", "") @@ -161,6 +168,17 @@ function _find_package(vcpkg, vcpkgdir, name, opt) return end + -- check that required features are installed + -- e.g. curl[mbedtls] should have curl_*_triplet_mbedtls.list in info directory + if required_features then + for _, feature in ipairs(required_features) do + local feature_infofile = find_file(format("%s_*_%s_%s.list", name, triplet, feature), infodirs) + if not feature_infofile then + return + end + end + end + -- find dependency package local result = nil local _, dependinfo = try { function () return os.iorunv(vcpkg, {"depend-info", name, "--sort=reverse", "--triplet=" .. triplet}) end } -- cgit v1.3.1 From a3fa1adf39a11074b516d3ffa27d77a182aa070b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Mar 2026 23:26:15 +0800 Subject: improve vcpkg --- xmake/modules/package/manager/vcpkg/install_package.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index 021e30d9a..e7c0fa930 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -56,6 +56,10 @@ function _install_for_classic(vcpkg, name, opt) table.insert(argv, "--debug") end + -- allow rebuilding packages when features change + -- @see https://github.com/xmake-io/xmake/issues/7388 + table.insert(argv, "--recurse") + -- install package os.vrunv(vcpkg, argv) end -- cgit v1.3.1 From 9ccfd524267021fbe5bbc8730e2c8891c62f1702 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Mar 2026 23:29:07 +0800 Subject: improve to find package with features in vcpkg --- .../modules/package/manager/vcpkg/find_package.lua | 47 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 531137b29..33ad3b755 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -131,6 +131,40 @@ function _get_package_info(name, triplet, infodirs, arch, plat, mode) return result end +-- get installed features from vcpkg status file +-- @see https://github.com/xmake-io/xmake/issues/7388 +function _get_installed_features(name, triplet, statusdirs) + local features = {} + for _, statusdir in ipairs(statusdirs) do + local statusfile = path.join(statusdir, "status") + if os.isfile(statusfile) then + local statusdata = io.readfile(statusfile) + if statusdata then + -- parse dpkg-like status entries, separated by blank lines + -- e.g. + -- Package: curl + -- Feature: openssl + -- Architecture: x64-windows-static-md + -- Status: install ok installed + -- + statusdata = "\n" .. statusdata .. "\n\n" + for entry in statusdata:gmatch("\n\n(.-)\n\n") do + local pkg = entry:match("Package:%s*(%S+)") + local arch = entry:match("Architecture:%s*(%S+)") + local feature = entry:match("Feature:%s*(%S+)") + local status = entry:match("Status:%s*(.-)\n?$") + if pkg == name and arch == triplet and status and status:find("installed", 1, true) then + if feature then + table.insert(features, feature) + end + end + end + end + end + end + return features +end + function _find_package(vcpkg, vcpkgdir, name, opt) -- get configs @@ -168,12 +202,17 @@ function _find_package(vcpkg, vcpkgdir, name, opt) return end - -- check that required features are installed - -- e.g. curl[mbedtls] should have curl_*_triplet_mbedtls.list in info directory + -- check that required features are installed via vcpkg status file + -- @see https://github.com/xmake-io/xmake/issues/7388 if required_features then + local statusdirs = {} + if opt.installdir then + table.insert(statusdirs, path.join(opt.installdir, "vcpkg_installed", "vcpkg")) + end + table.insert(statusdirs, path.join(vcpkgdir, "installed", "vcpkg")) + local installed_features = _get_installed_features(name, triplet, statusdirs) for _, feature in ipairs(required_features) do - local feature_infofile = find_file(format("%s_*_%s_%s.list", name, triplet, feature), infodirs) - if not feature_infofile then + if not table.contains(installed_features, feature) then return end end -- cgit v1.3.1 From d112f69b237378da0e655ddb9bacb55a3502c2a7 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Mar 2026 23:32:46 +0800 Subject: improve to find package again --- .../modules/package/manager/vcpkg/find_package.lua | 54 +++++----------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 33ad3b755..c839a8758 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -131,38 +131,18 @@ function _get_package_info(name, triplet, infodirs, arch, plat, mode) return result end --- get installed features from vcpkg status file +-- check if the required features are installed via `vcpkg list` -- @see https://github.com/xmake-io/xmake/issues/7388 -function _get_installed_features(name, triplet, statusdirs) - local features = {} - for _, statusdir in ipairs(statusdirs) do - local statusfile = path.join(statusdir, "status") - if os.isfile(statusfile) then - local statusdata = io.readfile(statusfile) - if statusdata then - -- parse dpkg-like status entries, separated by blank lines - -- e.g. - -- Package: curl - -- Feature: openssl - -- Architecture: x64-windows-static-md - -- Status: install ok installed - -- - statusdata = "\n" .. statusdata .. "\n\n" - for entry in statusdata:gmatch("\n\n(.-)\n\n") do - local pkg = entry:match("Package:%s*(%S+)") - local arch = entry:match("Architecture:%s*(%S+)") - local feature = entry:match("Feature:%s*(%S+)") - local status = entry:match("Status:%s*(.-)\n?$") - if pkg == name and arch == triplet and status and status:find("installed", 1, true) then - if feature then - table.insert(features, feature) - end - end - end - end +function _has_installed_features(vcpkg, name, triplet, required_features) + for _, feature in ipairs(required_features) do + local listinfo = try { function () + return os.iorunv(vcpkg, {"list", name .. "[" .. feature .. "]:" .. triplet}) + end} + if not listinfo or listinfo:trim() == "" then + return false end end - return features + return true end function _find_package(vcpkg, vcpkgdir, name, opt) @@ -202,20 +182,10 @@ function _find_package(vcpkg, vcpkgdir, name, opt) return end - -- check that required features are installed via vcpkg status file + -- check that required features are installed -- @see https://github.com/xmake-io/xmake/issues/7388 - if required_features then - local statusdirs = {} - if opt.installdir then - table.insert(statusdirs, path.join(opt.installdir, "vcpkg_installed", "vcpkg")) - end - table.insert(statusdirs, path.join(vcpkgdir, "installed", "vcpkg")) - local installed_features = _get_installed_features(name, triplet, statusdirs) - for _, feature in ipairs(required_features) do - if not table.contains(installed_features, feature) then - return - end - end + if required_features and not _has_installed_features(vcpkg, name, triplet, required_features) then + return end -- find dependency package -- cgit v1.3.1 From c03f3c5fbb20377215ea4c1c7240b4fc3da7722f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Mar 2026 23:52:08 +0800 Subject: fix vcpkg dependinfo --- xmake/modules/package/manager/vcpkg/find_package.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index c839a8758..563521889 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -189,8 +189,15 @@ function _find_package(vcpkg, vcpkgdir, name, opt) end -- find dependency package + -- pass features to depend-info to get the complete dependency tree + -- e.g. curl[mbedtls] needs mbedtls libraries + -- @see https://github.com/xmake-io/xmake/issues/7388 + local depend_name = name + if required_features then + depend_name = name .. "[" .. table.concat(required_features, ",") .. "]" + end local result = nil - local _, dependinfo = try { function () return os.iorunv(vcpkg, {"depend-info", name, "--sort=reverse", "--triplet=" .. triplet}) end } + local _, dependinfo = try { function () return os.iorunv(vcpkg, {"depend-info", depend_name, "--sort=reverse", "--triplet=" .. triplet}) end } if dependinfo then for _, line in ipairs(dependinfo:split("\n", {plain = true})) do if not line:startswith("vcpkg-") then -- cgit v1.3.1