使用“cabal v2-install”构建可执行文件时冻结所有依赖项

Freezing all dependencies when building executables with `cabal v2-install`

我正在构建一个 Docker 图像,我想在其中捆绑多个可执行文件。每个可执行文件都在不同的包中定义,在我的例子中是 pandocpandoc-citeprocpandoc-crossref。在基于 Debian/Ubuntu 的系统上,构建应尽可能合理地重现。

我想做的是使用(类似于)cabal.project.freeze 文件来确保所有后续构建都将使用相同的包。

我知道我可以修复可执行文件的版本:

cabal v2-install pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1

但这不会修复传递依赖项的版本,因此在不同时间重建可能会导致构建结果略有不同。我可以在此设置中以某种方式创建和使用 freeze 文件吗?使用 v2-freeze 在这里似乎没有用:

$ cabal new-freeze pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1
cabal: 'freeze' doesn't take any extra arguments: pandoc-2.7.3
pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1

好的,可能有更好的内置方法来做这种事情,但在真正的阴谋集团专家出现之前,这里有一个可能适合你的 hacky 解决方法。

基本计划是这样的:临时用您关心的三个包创建一个项目——足够长的时间来获得一个冻结文件——然后使用一些简单的文本编辑器宏将冻结文件变成一个v2-install 命令。所以:

% cabal unpack pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1
% echo >cabal.project packages: pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1
% cabal v2-freeze
% sed "s/^constraints: /cabal v2-install pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1 --constraint '/;s/^ \+/--constraint '/;s/,$/' \\/;$s/$/'/" cabal.project.freeze >cabal-v2-install.sh

哇哦,最后那句太难吃了。它说:

# Replace the starting "constraints" stanza with the v2-install command we want to
# run. The first line of the stanza includes a constraint, so prefix it with
# --constraint and start a quote.
s/^constraints: /cabal v2-install pandoc-2.7.3 pandoc-citeproc-0.16.2 pandoc-crossref-0.3.4.1 --constraint '/
# The line we just produced doesn't start with spaces, so this only fires on the
# remaining lines. On those lines, it prefixes --constraint and starts a quote.
s/^ \+/--constraint '/
# Close the quote begun on each line, and replace cabal's line-continuation
# character (,) with a shell's line-continuation character (\). The $ and \ are
# escaped because we are inside the current shell's ""-quoted string.
s/,$/' \\/
# The last line doesn't have a line-continuation character, but still needs its
# quote closed. The two occurrences of $ are escaped because we are inside the
# current shell's ""-quoted string.
$s/$/'/

如果需要,您也可以在编辑器中手动执行这些操作。在此过程结束时,您可以 运行 在一个临时目录中以方便之后的清理,您应该有一个名为 cabal-v2-install.sh 的文件,其中包含一个命令,该命令将 select 完全相同的版本和所有涉及的包的标志,包括依赖项。