在 Guix 中,如何找出清单中的哪个包向配置文件添加了特定的依赖项?

在 Guix 中,如何找出清单中的哪个包向配置文件添加了特定的依赖项?

我已经使我的 Guix 系统完全是声明性的,总是通过guix package -m mymanifest.scm.

有时,由于依赖关系冲突,这会失败。例如,现在gcc-toolchain我的清单中有数十个其他软件包,并且显示此消息:

guix package: error: profile contains conflicting entries for gcc-toolchain
guix package: error:   first entry: [email protected] /gnu/store/rfm800pq3q2midj29a4xlikdzjp1ps2l-gcc-toolchain-12.3.0
guix package: error:   second entry: [email protected] /gnu/store/ks87cpc36kh8hqwr569pks4yrzfl7mnv-gcc-toolchain-11.3.0
hint: You cannot have two different versions or variants of `gcc-toolchain' in the same profile.

我想gcc-toolchain清单中包含的是 12.3.0,并且其他一些包具有[email protected](间接)依赖项。但我不知道那是哪个包。

在这种特殊情况下,问题很容易解决,因为我也包含gcc在清单中,这导致了警告package 'gcc' has been superseded by 'gcc-toolchain',并且删除gcc似乎已经解决了问题。

但是,我想要一种更通用的适用方法来查找“有问题的”包。也就是说,给定一个清单文件,例如mymanifest.scm,我如何找出给定包(例如[email protected],)通过哪个依赖链最终出现在配置文件中?

我通常会进行二分搜索,只需注释掉(或返回)一半的包,然后查看问题何时消失(或重新出现),但这是一个手动且繁琐的过程。

我自己可以自动化执行此操作的丑陋天真的方法是循环遍历所有包,调用guix graph每个包,然后 grep 查找有问题的依赖项。更好的办法是弄清楚guix graph正在做什么,并针对整个清单执行此操作。或者也许将清单转换为包(空,除了依赖项),然后调用guix graph它。但可能有更好的方法。

答案1

总之:您可以通过单独构建清单的子集、从guix build -m manifest.scm每个清单中列出的包的存储地址获取、循环它们并使用 grepguix gc --requisites搜索它们的递归依赖项来暂时防止冲突。

由于您的配置文件当前无法构建,因此您应该将尝试添加的新软件包与它们冲突的旧软件包分开。或者,如果冲突发生在新包中,则将它们分开。包如何分发并不重要,重要的是要将您想要检查的所有包成功安装在商店中(以便您可以使用guix gc --requisites)以及一些清单,您可以从中以编程方式获取它们的路径。

首先在每个清单上运行guix build一次,以确保其成功构建并避免处理解析编译日志。然后第二次,它只会输出清单中包含的包的路径:

$ guix build -m manifest.scm
/gnu/store/jsk7igg8kd48blg5d6psb0rg120v68gw-xdot-1.1
/gnu/store/4dzv8avq7jyzybqvn3bj3c3bildi2pcc-graphviz-7.0.1-doc
/gnu/store/vsnrha979rs4sgmv2ynqvzd9dr5mj2mc-graphviz-7.0.1

然后,您可以循环访问此列表以guix gc --requisites调用每个包,并搜索您感兴趣的依赖项(其在存储中的名称,如错误消息中所示)。这是一个例子fish

for manifest in manifest1.scm manifest2.scm
    for package in (guix build -m $manifest)
        if guix gc -R $package | grep -q '/gnu/store/ks87cpc36kh8hqwr569pks4yrzfl7mnv-gcc-toolchain-11.3.0'
            echo $package
        end
    end
end

它将根据 递归地列出清单中的所有包[email protected]

可能与问题没有直接关系,但为了完整性:

如果您需要搜索商店中已有的配置文件的依赖项,并且您不能/不想使用guix build(如果您没有其清单,或者 guix 需要重新下载 GB 的构建工具)等):您还可以从配置文件中恢复原始包列表。

一般来说,如果某个配置文件没有被垃圾收集,那么 中将会有一个指向它的链接/var/guix/profiles/per-user/。如果您正在查找guix package -m mymanifest.scm(其上次成功构建,不包含冲突的包)使用的配置文件,您可以在商店中找到地址:

$ readlink -f ~/.guix-profile
/gnu/store/…-profile

获得配置文件的路径后,第二步是查找原始清单中的包的路径。guix gc --references /gnu/store/…-profile似乎还列出了它们的一些依赖项。为了仅获取您显式安装的软件包,我的技巧是使用软件包列表的缩进/gnu/store/…-profile/manifest:第一级软件包有 6 个空格,它们的依赖项有 10 个,等等:

grep -E '^ {6}"/gnu/store/' /gnu/store/…-profile/manifest | cut -d'"' -f 2

然后你会得到与 相同的列表guix build,减去由具有多个输出的包引起的双精度(例如上面示例中的 graphviz)。

相关内容