Bitcoin Core 可自举构建环境搭建指南:Guix 的五种安装方式、systemd 服务配置与源码构建排错 Bitcoin Core 可自举构建环境搭建指南Guix 的五种安装方式、systemd 服务配置与源码构建排错【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin本文基于 Bitcoin Core 仓库的 contrib/guix/INSTALL.md 编写系统讲解如何为 Bitcoin Core 搭建用于可自举bootstrappable构建的 Guix 环境从五种安装方案的选型对比、源码构建的完整流程依赖安装、--localstatedir配置、guix-daemon-original服务到/etc/profile.d环境集成、root 级guix pull与常见构建失败的排错手段。读完本文你将能够独立完成一次 Guix 安装、通过官方 checklist 验证环境并顺利衔接contrib/guix/guix-build的可复现构建流程。1. 背景为什么 Bitcoin Core 需要 Guixcontrib/guix/README.md 指出该目录包含执行可自举 Bitcoin Core 构建所需的全部文件。自举性的意义在于通过审计并复现工具链而不是盲目信任二进制下载来进一步强化二进制安全保证。Bitcoin Core 选择以功能性包管理器 Guix作为实现手段。因此contrib/guix/INSTALL.md解决的是构建链条上的第一环在你的机器上一次性每机器一次安装并配置好 Guix。README 同时给出了保守的磁盘空间要求/gnu/store所在分区至少16GB可用空间每计划构建一个平台三元组platform triple需额外8GB可用空间。安装完成后实际的构建入口是仓库中的 guix-build 脚本。2. 五种安装方案对比INSTALL.md 为使用者提供了五条路径核心差异在于维护方、难度、可安装版本粒度与信任级别。以下是原文档的完整方案清单外部指引已按仓库内文档位置对应方案维护方难度适用范围版本粒度安装形态与信任1. 官方 shell 安装脚本Guix 开发者最简单自动完成大部分设置几乎所有 Linux 发行版仅最新发行版二进制需较高信任脚本需以 root 运行运行前应检查脚本内容2. 官方二进制 tarballGuix 开发者中等需完整手动设置几乎所有 Linux 发行版任意发行版二进制需较高信任3. fanquake 的容器镜像fanquake简单自动完成部分设置任何可运行容器镜像的环境Docker/Podman任意发行版二进制需较高信任4. 发行版维护的软件包各发行版 Guix 维护者中等需手动设置仅打包了 Guix 的发行版由打包者决定的版本源码或二进制取决于发行版5. 从源码构建你自己困难但回报高可在大多数 Linux 发行版上完成任意 commit粒度最细源码安装信任级别最低选型建议很直接追求省事且信任二进制选方案 1/2/3追求最小信任可以构建到任意 Guix commit选方案 5。后文将方案 5 作为展开重点因为它涵盖了方案 1、2 中由安装脚本自动完成的那些幕后步骤如/etc/profile.d条目、daemon 服务理解它对排查其他安装方式的问题同样有帮助。3. 方案 1/2官方安装脚本或二进制 tarball两种方式的安装步骤都以 GNU Guix Manual 的 Binary Installation 章节为准以仓库文档写作时的状态为准。文档特别指出两条实践要点二进制 tarball 的手动安装步骤大体上等价于 shell 安装脚本自动做的事。在文档写作时2021 年 7 月 5 日shell 安装脚本会自动创建/etc/profile.d条目而二进制 tarball 的安装说明并不要求你创建它——但为了良好的桌面集成你大概率需要它做法见第 7.1 节的/etc/profile.d/guix.sh完整脚本。无论选哪种方式对/etc/profile.d的修改在下一次 shell 或桌面会话才生效应注销后重新登录。4. 方案 4发行版维护的软件包4.1 Debian / Ubuntu近期 Debian/Ubuntu 官方仓库中已不再提供guix软件包可直接改用本文档中的其他安装方式。若你此前通过apt安装过可用以下命令移除sudo apt purge guix4.2 Arch LinuxAURGuix 在 AUR 中以guix包提供按 Arch Linux Wiki 的 AUR 安装说明操作即可。文档记录了一个值得注意的坑在 AUR 构建时若 Guix 构建目录的路径长度超过 36 个字符check阶段会因 shebang 行的历史性字符长度限制而失败由于check在耗时漫长的build阶段之后才执行建议跳过check阶段makepkgmakepkg --nocheck ...yayyay --mflags--nocheck ...paruparu --nocheck ...或事先检查构建目录长度对makepkg用户执行pwd | wc -c。5. 方案 5从源码构建 Guix重点这是困难但回报高的路径适合希望最小化信任、最大化可定制性例如构建某个特定 Guix commit的用户。建议先通读本节再动手——文档原文的告诫是这会帮你省去很多不必要的疼痛。5.1 安装通用构建工具先安装后续构建大多会用到的基础工具。文本转换/i18n 类autopoint有时打包在gettext中help2manpo4atexinfo构建系统类支持 C11 的glibtool、autoconf、automakepkg-config有时打包为pkgconfmake、cmake杂项git、gnupg、python35.2 构建并安装 Guix 的依赖依赖清单的权威来源是 Guix Reference Manual 的 Requirements 章节以官方手册最新版为准。多数发行版已将其中大部分甚至全部依赖打包无需逐一手动构建。捷径如果 Guix 在你的发行版中有软件包即使你最终选择源码构建也可以只安装其构建依赖。以 Ubuntu/Debian 为例启用 deb-src 并安装 Guix 构建依赖sed -i s|# deb-src|deb-src|g /etc/apt/sources.list apt update apt-get build-dep -y guix若此步骤成功大概率可直接跳到 5.4 节。5.3 依赖安装的四个实战要点Guile多版本共存的边角情况推荐只安装所需版本的 Guile避免构建系统分不清该用哪个 Guile。若坚持安装多个版本则必须一致地为 Guix 及其所有依赖的./configure调用指定GUILE_EFFECTIVE_VERSION3.0。安装 Guile 时注意 Debian 系发行版将-dev后缀包与非-dev包拆分两者都要装例如在 Debian/Ubuntu 上安装 Guile v3.0apt install guile-3.0 guile-3.0-dev混合使用发行版软件包与源码构建的软件包多数发行版只打包了 Guix 的部分依赖。混合安装时发行版包通常装到/usr而源码构建的默认./configure前缀是/usr/local。若未把源码包显式配置为--prefix/usr就必须补充GUILE_LOAD_PATH与GUILE_LOAD_COMPILED_PATH让 Guile 到正确的前缀下找到源码构建的包。以 Guile v3.0 为例将以下内容加入.profile或.bash_profile或对当前 shell 临时生效# 帮助 Guile v3.0.x 在 /usr/local 下找到包 export GUILE_LOAD_PATH/usr/local/share/guile/site/3.0${GUILE_LOAD_PATH::}$GUILE_LOAD_PATH export GUILE_LOAD_COMPILED_PATH/usr/local/lib/guile/3.0/site-ccache${GUILE_LOAD_COMPILED_PATH::}$GUILE_COMPILED_LOAD_PATH注意这些环境变量在./configure阶段就会被用来查找包因此只要你打算使用/usr以外的前缀就应尽早设置。构建源码包的一般流程多数依赖使用 autoconf 风格构建系统判断依据仓库根目录存在configure.ac通用流程如下——先克隆并检出最新 releasegit clone 依赖仓库地址/依赖名.git cd 依赖 git tag -l # 查看最新 release git checkout latest-releaseautoconf 类仓库根存在./autogen.sh或configure.ac./autogen.sh || autoreconf -vfi ./configure --prefixprefix make sudo make installCMake 类仓库根存在CMakeLists.txtmkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIXprefix sudo cmake --build . --target installGuile 绑定包需要对应的-dev包构建绑定时原包的-dev后缀版本必须已安装例如在 Debian 系上构建Guile-zlib需要zlib1g-dev使用绑定包时-dev包同样必须存在——这在发行版打包不当时尤其容易踩坑如 Ubuntu Focal 的guile-sqlite3不会自动安装libsqlite3-dev。文档给出的 Debian 相关对应关系表Guile 绑定包对应-devDebian 包guile-gcryptlibgcrypt-devguile-gitlibgit2-devguile-gnutls无guile-json无guile-lzlibliblz-devguile-sshlibssh-devguile-sqlite3libsqlite3-devguile-zlibzlib1g-devguile-git实际依赖libgit2 1.1guile-git自 v0.5.2 起宣称只需libgit2 0.28.0实际却要求libgit2 1.1否则它会被origin/keyring这类引用搞混——把本应理解为origin 远程的 keyring 分支的引用误当作名字就叫 origin/keyring 的分支。Ubuntu Focal 恰好打包了libgit2 v0.28.4并以此构建guile-git正落在该坑内。若你处于此情形需要从源码同时构建libgit2 v1.1.x与guile-git。5.4 构建并安装 Guix 本体克隆 Guix 并检出最新 release文档写作时2023 年 11 月最新 release 为v1.4.0git clone Guix 源码仓库地址 cd guix git branch -a -l origin/version-* # 查看最新 release 分支 git checkout latest-release引导构建系统然后配置、构建、安装./bootstrap ./configure --localstatedir/var make -j$(nproc) sudo make install两个注意点--localstatedir/var是推荐参数。若你今后打算修改 Guix 本身所有后续的 Guix./configure调用都必须提供相同的--localstatedir值详见 Guix 手册 Requirements 章节的末段说明。构建耗时较长耐心等待。5.5 源码构建后的 daemon 服务修复安装完成后guix位于${bindir}未覆盖目录变量时通常是/usr/local/bin。但问题在于Guix 为 Upstart、systemd、SysV、OpenRC 安装的 init 脚本位于${libdir}启动的是${localstatedir}/guix/profiles/per-user/root/current-guix/bin/guix-daemon——这个路径在你以 root 执行首次guix pull见 7.2 节之前并不存在。解决办法创建指向刚构建安装的二进制的-original版服务。以 systemd 为例以 root 运行# 基于 guix-daemon.service 创建 guix-daemon-original.service libdir# 按你的 PREFIX 设置默认 /usr/local/lib bindir$(dirname $(command -v guix-daemon)) sed -E -e s|/\S*/guix/profiles/per-user/root/current-guix/bin/guix-daemon|${bindir}/guix-daemon| ${libdir}/systemd/system/guix-daemon.service /etc/systemd/system/guix-daemon-original.service chmod 664 /etc/systemd/system/guix-daemon-original.service # 让 systemd 识别新服务 systemctl daemon-reload # 停止并禁用无法工作的 guix-daemon.service systemctl stop guix-daemon systemctl disable guix-daemon # 启动并启用可工作的 guix-daemon-original.service systemctl enable guix-daemon-original systemctl start guix-daemon-original另外还需创建 guix-daemon 构建用户/组细节参照 Guix Reference Manual 的 Build Environment Setup 章节。6. 安全模型安装后必须做的决策无论用哪种方式安装构建前都要在 contrib/guix/README.md 的 Choosing your security model 一节中确定是否使用 substitutes预构建包。三种选择与 INSTALL.md 的排错内容直接相关使用 substitutes先授权签名密钥写入/etc/guix/acl可用guix archive --authorize导入官方构建农场公钥再指定 substitute 服务器guix-daemon --substitute-urls、guix cmd --substitute-urls或对contrib/guix下脚本设置SUBSTITUTE_URLS环境变量临时禁用guix cmd --no-substitutes或export ADDITIONAL_GUIX_COMMON_FLAGS--no-substitutes默认禁用给guix-daemon传--no-substitutes需改 init 脚本。从仓库源码可以印证这一机制prelude.bash 中的time-machine()函数会把SUBSTITUTE_URLS展开为--substitute-urls并连同ADDITIONAL_GUIX_COMMON_FLAGS、ADDITIONAL_GUIX_TIMEMACHINE_FLAGS一并传给guix time-machine而 guix-build 在执行每个平台三元组的构建前会用guix shell --container --pure --no-cwd --share$PWD/bitcoin ...把仓库绑定挂载到容器内固定路径/bitcoin下从而消除主机路径差异带来的不可复现因素。7. 可选设置让环境原汁原味完成第 36 节后你已经可以按 README 的 Usage 一节 使用 Guix 构建 Bitcoin Core以下小节用于进一步打磨环境。7.1 添加/etc/profile.d条目若你通过 shell 安装脚本、fanquake 容器镜像或旧版 Debian 包安装本节不适用。原理Guix 的自我更新是非侵入式的——它不修改/usr/local/bin/guix。guix pull之后更新的是/var/guix/profiles/per-user/$USER/current-guix符号链接为$HOME/.config/guix/currentguix install之后更新的是/var/guix/profiles/per-user/$USER/guix-profile符号链接为$HOME/.guix-profile。因此若$HOME/.config/guix/current/bin不在$PATH中guix pull对你实际使用的guix毫无影响。guix pull/guix install结束后打印的hint: Consider setting the necessary environment variables...提示即是此意而逐个用户手动 source 十分繁琐故推荐写入/etc/profile.d。创建/etc/profile.d/guix.sh内容为# _GUIX_PROFILE: guix pull 生成的 profile _GUIX_PROFILE$HOME/.config/guix/current if [ -L $_GUIX_PROFILE ]; then export PATH$_GUIX_PROFILE/bin${PATH::}$PATH # 导出 INFOPATH使更新后的 info 页面可被 /usr/bin/info 和/或 # $GUIX_PROFILE/bin/info 找到并阅读 # INFOPATH 未设置时追加冒号让 Emacs 检索 Info-default-directory-list export INFOPATH$_GUIX_PROFILE/share/info:$INFOPATH fi # GUIX_PROFILE: 用户默认 profile GUIX_PROFILE$HOME/.guix-profile [ -L $GUIX_PROFILE ] || return GUIX_LOCPATH$GUIX_PROFILE/lib/locale export GUIX_PROFILE GUIX_LOCPATH [ -f $GUIX_PROFILE/etc/profile ] . $GUIX_PROFILE/etc/profile # 将 Guix 安装目录纳入 XDG_DATA_DIRS export XDG_DATA_DIRS$GUIX_PROFILE/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}同样需注销并重新登录才生效。7.2 以 root 执行guix pull先按 README 的安全模型一节 调整guix/guix-daemon参数——因为guix pull可能从 substitute 服务器拉取预构建包。源码构建时${localstatedir}/guix/profiles/per-user/root/current-guix尚不存在它需要由某个旧版 Guix以 root 身份 pull 生成因此必须补一次 root 级 pullsudo --login guix pull --branchversion-latest-release-version # 或 sudo --login guix pull --commit特定commit要点guix pull是长耗时过程使用--no-substitutes时尤其如此构建问题参见第 8 节排错裸guix pull不指定 commit/branch会拉取 master 最新 commit大概率没问题但不推荐源码安装后可能遇到error: while creating symlink /root/.config/guix/current No such file or directory解决方式是sudo mkdir -p /root/.config/guix后重试。pull 成功后${localstatedir}/guix/profiles/per-user/root/current-guix即被填充。重启 daemon 以使用新拉取的 guix从源码构建的用户若你已按 5.5 节修复了 argv[0]现在可以换回官方服务即指向 pull 后路径的guix-daemon.servicesystemctl stop guix-daemon-original systemctl disable guix-daemon-original systemctl enable guix-daemon systemctl start guix-daemon注意若你在guix-daemon-original.service中设置了--no-substitutes等定制记得在$libdir/systemd/system/guix-daemon.service中同样设置。Debian/Ubuntu 发行版包用户需创建指向新版guix的guix-daemon-latest服务# 基于 guix-daemon.service 创建 guix-daemon-latest.service sed -E -e s|/usr/bin/guix-daemon|/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon| /etc/systemd/system/guix-daemon.service /lib/systemd/system/guix-daemon-latest.service chmod 664 /lib/systemd/system/guix-daemon-latest.service # 让 systemd 识别新服务 systemctl daemon-reload # 停止并禁用旧的 guix-daemon.service systemctl stop guix-daemon systemctl disable guix-daemon # 启动并启用 guix-daemon-latest.service systemctl enable guix-daemon-latest systemctl start guix-daemon-latestArch Linux AURlantw44 包用户更新后 Guix 的 systemd 单元名为guix-daemon-latest.servicesystemctl stop guix-daemon systemctl disable guix-daemon systemctl enable guix-daemon-latest systemctl start guix-daemon-latest其他安装方式直接systemctl restart guix-daemon即可。7.3 完整性检查清单若你希望环境无懈可击按以下清单逐项核对/etc/profile.d/guix.sh存在且每次 shell 登录时都会加载guix describe不再输出guix describe: error: failed to determine origin而是类似Generation 38 Feb 22 2021 16:39:31 (current) guix f350df4 repository URL: guix 仓库地址 branch: version-1.2.0 commit: f350df405fbcd5b9e27e6b6aa500da7f101f41e7guix-daemon正从${localstatedir}/guix/profiles/per-user/root/current-guix运行。8. 排错8.1 某个 derivation 构建失败典型输出如下building /gnu/store/...-foo-3.6.12.drv... / check phase note: keeping build directory /tmp/guix-build-foo-3.6.12.drv-0 builder for /gnu/store/...-foo-3.6.12.drv failed with exit code 1 build of /gnu/store/...-foo-3.6.12.drv failed View build log at /var/log/guix/drvs/../...-foo-3.6.12.drv.bz2. cannot build derivation /gnu/store/...-qux-7.69.1.drv: 1 dependencies couldnt be built cannot build derivation /gnu/store/...-bar-3.16.5.drv: 1 dependencies couldnt be built cannot build derivation /gnu/store/...-baz-2.0.5.drv: 1 dependencies couldnt be built guix time-machine: error: build of /gnu/store/...-baz-2.0.5.drv failed含义是foo构建失败而它是qux、bar、baz的依赖。关键最后一个 failed 行未必是根因第一个failed 行才是。多数失败源于偶发测试失败或包构建/测试套件在多线程下出问题。用单线程方式只重建这一个 derivation别忘了按你的安全模型补上--no-substitutes等标志guix build --cores1 /gnu/store/...-foo-3.6.12.drv单线程仍失败时用less查看构建日志路径以失败输出中显示为准bzcat /var/log/guix/drvs/../...-foo-3.6.12.drv.bz2 | less构建目录也会被保留在/tmp/guix-build-foo-3.6.12.drv-0多次失败时可能是/tmp/...drv-1、/tmp/...drv-2以失败输出的最新信息为准。仓库内的 guix-build 对 Guix 环境构建失败也做了配套处理从源码注释可见time-machine()携带--keep-failed标志以保留失败环境guix shell调用携带--keep-failed便于事后调试。8.2 python(-minimal)[Errno 84] Invalid or incomplete multibyte or wide character当$TMPDIR默认 /tmp所在的文件系统拒绝 UTF-8 字符集之外的字符时会出现例如设置了utf8onlyon的 ZFS 文件系统。可参考 CPython 上游 issue 81765。8.3 openssl-1.1.1l 与 openssl-1.1.1nOpenSSL 的测试套件中包含会在证书过期后失败的用例。可用下节 GnuTLS 的变通方案openssl-1.1.1l 以2022-05-01作为回拨日期。8.4 GnuTLStest-suite FAIL: status-request-revoked该 derivation 通常表现为/gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv这是使用 Guix v1.2.0 的非 substitute 构建者最常撞上的问题GnuTLS 某测试使用了一张 2020-10-24 已过期的硬编码证书。更麻烦的是该 GnuTLS derivation 在 Guix 依赖图中比较特殊--without-tests之类的包转换标志对它无效。最简解法是安装更新版本的 Guix变通方案有三变通 1仅为这一个 derivation 使用 substitute若已授权官方 Guix 构建农场的密钥授权流程见 README 的 Step 1: Authorize the signing keysguix build --substitute-urlshttps://ci.guix.gnu.org /gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv若不想长期保留构建农场密钥可按 README 的 Removing authorized keys 一节 编辑/etc/guix/acl移除对应条目。变通 2临时回拨系统时钟关闭 NTP → 设置时间 → 构建 → 恢复sudo timedatectl set-ntp no sudo date --set 01 oct 2020 15:00:00 guix build /gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv sudo timedatectl set-ntp yes变通 3在 Guix 源码中为该 derivation 禁用 tests 阶段通过arguments选项关闭其tests阶段例如为 openssl-1.1 禁用 check 阶段diff --git a/gnu/packages/tls.scm b/gnu/packages/tls.scm --- a/gnu/packages/tls.scm b/gnu/packages/tls.scm (define-public openssl-1.1 (arguments (#:parallel-tests? #f #:tests? #f #:test-target test8.5 coreutilsFAIL: tests/tail-2/inotify-dir-recreate该 inotify 测试在 overlayfsDocker 默认文件系统等远程文件系统上会因文件系统被误判为非远程而失败。相对简单的规避是让/tmpguix-daemon执行构建的位置挂载传统文件系统Docker 用户可改用 volume、从宿主机 bind mount或在内存/swap 充足时用--tmpfs挂载 tmpfs。补充背景coreutils 上游已提交对应 bugGuix 1.4.0 起已包含跳过该测试的提交。8.6 zdiff3若全局 git 配置中merge.conflictstyle被设为zdiff3guix更新 channel 时会报错Updating channel guix from Git repository at ...guix.git... guix time-machine: error: Git error: unknown style zdiff3 given for merge.conflictstyle修复方式是把该值改回diff3git config --global merge.conflictstyle diff3值得注意的是prelude.bash 中time-machine()会固定拉取--commitc5eee3336cc1d10a3cc1c97fde2809c3451624d3这一个 Guix commit——构建所用的 Guix 版本被仓库锁定这正是安装任何版本、拉取任意 commit的 INSTALL 文档与构建结果跨时间可复现之间得以调和的关键。9. 彻底清除 / 卸载 Guix若 Guix 安装已坏到无法挽回需要完全清除重来。步骤卸载 Guix 本体方式取决于当初如何安装Ubuntu 包sudo apt purge guix源码构建sudo make uninstall官方安装脚本为其加--uninstall参数运行Guix 手册有卸载说明移除所有构建用户与组。先用以下命令检查相关用户/组getent passwd | grep guix getent group | grep guix然后逐个删除sudo userdel user sudo groupdel group移除所有可能的 Guix 相关目录/var/guix//var/log/guix//gnu//etc/guix//home/*/.config/guix//home/*/.cache/guix//home/*/.guix-profile//root/.config/guix//root/.cache/guix//root/.guix-profile/10. 结语从安装到构建当本文流程走完并通过 7.3 节检查清单后Guix 环境已就绪。后续构建按 contrib/guix/README.md 执行在干净仓库顶层运行./contrib/guix/guix-build即可完成默认全部平台三元组的可复现构建构建前脚本会做一系列防御性检查——例如 guix-build 会拒绝在脏 worktree 上构建可用FORCE_DIRTY_WORKTREE覆盖、拒绝意外设置的SOURCE_DATE_EPOCH可用FORCE_SOURCE_DATE_EPOCH显式确认、并默认对HOSTSLinux x86_64/ARM/AArch64/RISC-V64/PowerPC64(LE)、Windows x86_64、macOS x86_64/AArch64逐一构建。构建结束后可用./contrib/guix/guix-clean清理中间工作目录、用./contrib/guix/guix-attest与./contrib/guix/guix-verify完成构建产物的签名与验证。安装只是起点理解为什么 daemon 需要-original/-latest服务变体为什么--localstatedir/var必须始终一致为什么 pull 后的 profile 路径必须进$PATH这三个问题是日后维护这套可自举构建环境的核心。【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考