diff options
| author | ruki <[email protected]> | 2026-06-23 14:07:27 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-06-23 14:07:27 +0800 |
| commit | 44711c34a5bfcb192df4985a30e4dfb1c4441c23 (patch) | |
| tree | 74233e858202b943169542b4b8e3edd68e9e9269 | |
| parent | bcd6a836dd03db0418a6f5c604d63c96f887483a (diff) | |
| parent | fd3181633dc59463bd40300c00d51816d0af6e03 (diff) | |
Merge pull request #7614 from xmake-io/cargo
improve cargo/install_package
| -rw-r--r-- | xmake/modules/package/manager/cargo/install_package.lua | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua index 1dd81a09e..71459f866 100644 --- a/xmake/modules/package/manager/cargo/install_package.lua +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -47,6 +47,90 @@ function _translate_local_path_in_deps(cargotoml, rootdir) io.writefile(cargotoml, content) end +-- is it a cargo workspace manifest? (it contains a [workspace] or [workspace.xxx] table) +function _is_workspace_manifest(content) + for _, line in ipairs(content:split("\n", {plain = true, strict = true})) do + if line:match("^%s*%[workspace[%].]") then + return true + end + end + return false +end + +-- get the workspace inheritance tables from the workspace root manifest +-- +-- if the given Cargo.toml is a member of a cargo workspace and uses workspace inheritance, +-- e.g. `anyhow.workspace = true`, `version.workspace = true`, `[lints] workspace = true`, +-- we need to inject the `[workspace.package]`/`[workspace.dependencies]`/`[workspace.lints]` +-- tables from the workspace root manifest, otherwise cargo will fail to resolve them, e.g. +-- +-- error inheriting `anyhow` from workspace root manifest's `workspace.dependencies.anyhow` +-- `workspace.dependencies` was not defined +-- +-- @see https://github.com/xmake-io/xmake/issues/7619 +-- https://doc.rust-lang.org/cargo/reference/workspaces.html#the-workspacedependencies-table +function _get_workspace_inherited_tables(cargo_toml) + + -- find the workspace root manifest by walking up + local rootmanifest + local dir = path.directory(path.absolute(cargo_toml)) + while dir and #dir > 0 do + local manifest = path.join(dir, "Cargo.toml") + if os.isfile(manifest) then + local content = io.readfile(manifest) + if content and _is_workspace_manifest(content) then + rootmanifest = manifest + break + end + end + local parentdir = path.directory(dir) + if parentdir == dir then + break + end + dir = parentdir + end + + -- not a workspace member, or the manifest itself is the workspace root (self-contained) + if not rootmanifest or path.absolute(rootmanifest) == path.absolute(cargo_toml) then + return + end + + -- extract all the [workspace.xxx] sub-tables, e.g. [workspace.package]/[workspace.dependencies]/[workspace.lints] + -- we do not copy the bare [workspace] table (members/exclude), otherwise cargo will search for the member crates. + local content = io.readfile(rootmanifest) + if not content then + return + end + local result = {} + local in_subtable = false + for _, line in ipairs(content:split("\n", {plain = true, strict = true})) do + local header = line:match("^%s*%[(.-)%]%s*$") + if header then + in_subtable = header:trim():startswith("workspace.") + if in_subtable then + table.insert(result, line) + end + elseif in_subtable then + table.insert(result, line) + end + end + if #result == 0 then + return + end + + -- translate the local paths in the workspace dependencies, they are relative to the workspace root directory + local rootdir = path.directory(rootmanifest) + local workspace_toml = table.concat(result, "\n") + workspace_toml = workspace_toml:gsub("path%s+=%s+\"(.-)\"", function (localpath) + if not path.is_absolute(localpath) then + localpath = path.absolute(localpath, rootdir) + end + localpath = localpath:gsub("\\", "/") + return "path = \"" .. localpath .. "\"" + end) + return workspace_toml +end + -- install package -- -- e.g. @@ -101,6 +185,13 @@ function main(name, opt) tomlfile:print("") tomlfile:print("[workspace]") tomlfile:print("") + -- inject the workspace inheritance tables if the given Cargo.toml is a workspace member, + -- e.g. `anyhow.workspace = true`. @see https://github.com/xmake-io/xmake/issues/7619 + local workspace_toml = _get_workspace_inherited_tables(configs.cargo_toml) + if workspace_toml then + tomlfile:write(workspace_toml) + tomlfile:print("") + end tomlfile:close() else local tomlfile = io.open(cargotoml, "w") |
