📖 本文由 Batocera 官方 Wiki 翻译整理,内容可能随版本更新而变化。


编译 Batocera.Linux 入门指南

想要亲手编译(Compile)属于自己的 Batocera 系统?官方最推荐的方法是使用专为开发定制的 Docker 容器(Container)。虽然你也可以直接在安装了 Ubuntu Linux 的机器上操作,但为了环境纯净和成功率,Docker 依然是首选。

【注意】:虽然通过 LXC 容器编译在技术上可行,但这并非官方推荐的做法,也不在技术支持范围内。

如果你对 Git 版本控制系统(Git) 还不太熟悉,建议在动手前先学习一下如何使用 Git 为 Batocera 贡献代码的基础知识。


硬件整备:工欲善其事,必先利其器

编译系统是一个非常耗费硬件资源的过程。你可以把它想象成在家里“手工打造一辆汽车”:你不仅需要一个足够大的车间(硬盘空间),还需要足够多的帮手(内存)和干活够快的设计师(CPU)。

1. 核心硬件要求

  • 处理器(CPU):需要性能较强。如果你拥有 8 核/16 线程以上的顶级处理器,那干活效率会翻倍。
  • 内存(RAM)
    • 底线:至少 8GB
    • 进阶:如果你要编译 MAME 这种大型模拟器,建议准备 12GB 以上
    • 高配:如果你想让多核 CPU 全力全速并发编译,可能需要超过 16GB 的内存。
  • 硬盘空间:每个目标平台需要准备 80GB 到 250GB 的空余空间。

2. 空间占用估算表

为了让你心里有数,这里有一份编译 Batocera 41 版本时的空间参考:

阶段/平台 所需空间(估算值)
源码下载(Sources download) 高达 120GB (x86_64 版本)
x86_64 平台编译 165GB
x86_wow64 附加空间 +35GB

第一步:安装必要的前提条件

在正式开始编译之前,你需要确保你的操作系统已经安装了所有必要的依赖包(Prerequisites)

生活化类比:这就像是在正式烹饪前,你得先买好案板、菜刀、调料和各种厨具。没有这些基础设施,就算你拿到了完美的食谱(源码),也无法开工。

除了最常见的 x86 平台,如果你打算为各类开发板(如树莓派)编译系统,可以参考以下各个平台的空间需求:

硬件平台 编译所需空间(Batocera 版本参考)
bcm2712 (树莓派 5 / rpi5) 105GB (Batocera 41)
bcm2711 (树莓派 4 / rpi4) 103GB (Batocera 41)
bcm2837 (树莓派 3 / rpi3) 80 GB
bcm2836 (树莓派 2 / rpi2) 130 GB (Batocera 40)
rk3326 74GB (Batocera 40)
rk3399 45GB (Batocera 40)
s905gen2 (radxa zero) 65 GB
rpizero (树莓派 Zero) 45 GB

【注意】:如果你打算在虚拟机(VM)里进行编译,请务必将 CPU 类型设置为“主机模式(Host)”。否则可能会遇到“缺少 CPU 指令集”的错误提示,例如在编译模拟器时报错:#error PCSX2 requires compiling for at least SSE 4.1


第二步:安装开发工具

如果你的电脑是第一次尝试编译程序,你需要先给它安装一套“工具箱”,比如 Git 和 Make 等基础工具。你可以选择一个一个单独安装,但在 Linux 中,最方便的方法是直接下载整个开发工具组包(Development group package)

生活化类比:这就像是你打算在家里做木工,你可以满大街跑去买锯子、锤子和刨子,但最省心的办法是直接去五金店买一整套专为木工设计的“新手大礼包”。

请根据你使用的系统版本运行相应的安装命令:

  • 针对 Ubuntu 用户
    • 直接运行:sudo apt-get install build-essential 即可安装基础开发工具。
  • 针对 Fedora 用户
    • 先运行:sudo dnf group info "Development Tools" "Development Libraries" 查看包含的内容。
    • 再运行:sudo dnf groupinstall "Development Tools" "Development Libraries" 进行安装。
  • 针对 Arch 用户
    • 直接运行:sudo pacman -S base-devel 即可一键安装。

如果你想让你的系统保持“极简”,那么在宿主操作系统中,你只需要安装 GitMake 这两个最基本的工具即可。剩下的所有编译环境,都已经被打包进 Docker 镜像(Docker Image) 里面了。


第三步:配置 Docker 环境

如果你已经在 Linux 系统中安装并配置好了 Docker,可以直接跳过本节,前往下方的“准备工作”部分。

生活化类比:Docker 就像是一个“集装箱”。它把编译 Batocera 所需要的所有零件和工具都整整齐齐地码放在一个集装箱里。你不需要在自己的电脑(码头)上到处乱放工具,只需要确保你的电脑能打开这个集装箱即可。

平台选择建议

【提示】:大多数开发者都选择在 Ubuntu Linux 上使用 Docker 来编译系统。截至目前,在 Windows 系统上运行 Docker 进行编译仍不够稳定。

此外,如果你使用的是 macOS Mojave 10.14 系统,只要以普通用户(非 root 权限)运行 Docker 容器,也是可以成功编译的。

各平台安装指南

  • Linux Ubuntu/Debian 用户

    • 第一步:安装 Docker。官方不建议直接使用系统自带的安装包,为了保证版本最新,请参考官方文档进行安装:https://docs.docker.com/engine/install/ubuntu/
    • 第二步:设置免根用户权限(Root privileges)运行。为了让你不需要每次都输入 sudo,请将你的用户加入“docker”组:运行 sudo usermod -aG docker 你的用户名
    • 第三步:使配置生效。运行完命令后,请先注销系统或重启,然后重新登录。
  • Fedora 用户
    (请参考对应的发行版安装步骤进行操作)

  • Fedora 用户:

    • 第一步:安装 Docker。官方不建议使用 Snap、AppImage 或 Flatpak 这些打包方式。为了系统的稳定性,请直接参考官方安装指南:https://docs.docker.com/engine/install/fedora/
    • 第二步:配置用户权限。为了让你在不使用根权限的情况下运行 Docker,需要将当前用户加入 docker 组。你可以参考 Fedora 官方说明
    • 第三步:万一失败的备选方案。如果上述方法不起作用,请依次在终端输入以下代码:

      sudo groupadd docker
      sudo gpasswd -a ${USER} docker
      sudo systemctl restart docker
      newgrp docker
    • 第四步:设置开机自启。输入 sudo systemctl enable docker,然后注销并重新登录系统。
  • 其他系统用户:


第四步:准备工作

在正式开始编译这个“庞然大物”之前,我们需要先把它的“蓝图”——也就是源代码下载到本地。

获取 Batocera.Linux 源代码

如果你已经准备好为 Batocera 提交拉取请求(Pull Request),也就是说你已经配置好了相关的开发环境,那么只需要执行以下简单的命令:


cd Batocera.Linux
git checkout master

完成这一步后,你就可以跳过后续的准备步骤,直接开始编译了。

生活化类比:这就像是你已经是一名熟练的建筑师,手里已经有了最新的设计图。你只需要切换到“主设计稿(Master 分支)”,就可以直接进场开工了。

选择一个工作目录(比如你的主目录 $HOME),我们要开始把 Batocera.Linux 的源代码“搬”到你的电脑上了。

获取源代码

  • 第一步:克隆代码仓库
    在终端输入以下指令,从 GitHub 上下载完整的代码库:

    git clone https://github.com/Batocera-Linux/Batocera.Linux.git
  • 第二步:进入项目目录
    下载完成后,我们要钻进这个文件夹里:

    cd Batocera.Linux
  • 第三步:初始化并更新子模块
    由于 Batocera 依赖一个名为 Buildroot 子模块(Submodule) 的核心组件,它默认不会随着代码库一起下载,所以你需要手动执行下面这两行命令来抓取它:

    git submodule init
    git submodule update

    【提示】:这个初始化操作你只需要做一次,以后就不必重复了。

编译阶段

简易编译法

为了降低上手难度,我们提供了一个 编译配置文件(Makefile),它能让整个编译过程像自动流水线一样顺滑。

1. 将你的账号加入 Docker 组

如果你在之前的准备工作中还没操作过这一步,请务必执行。否则,你在运行 Docker 时会频繁遇到权限障碍。

生活化类比:这就像是给你自己发一张“通行证”。有了它,你在操作 Docker 这个“集装箱”时就不用每次都向保安(系统管理员)申请临时授权了。

在大多数 Linux 系统中,执行这条命令即可:

sudo usermod -a -G docker $USER

输入密码确认后,请重启电脑(如果你是通过 SSH 远程连接的,请断开并重新连接)以使权限变更生效。

2. 启动 Docker 服务

如果你之前没有设置过 Docker 随系统开机自启,那么现在你需要手动把它叫醒。在大多数发行版中,你可以通过以下命令启动 Docker 守护进程(Docker daemon)


sudo systemctl start docker


sudo systemctl start docker.service

然后,请重启电脑,以确保 Docker 服务和权限都已经完全准备就绪。


3. 安装编译环境

现在,我们要开始搭建编译专用的“工坊”了。在终端运行:


make build-docker-image

【注意】:这个镜像包含了编译所需的所有依赖。每隔一段时间,你可能需要运行 make update-docker-image 来更新这个工坊里的工具,以确保它们跟上最新的标准。


4. 自定义工作目录

默认情况下,Batocera 会把下载的原始素材存放在 $(PROJECT_DIR)/dl 文件夹,而把加工好的成品放在 $(PROJECT_DIR)/output 文件夹。

你可以通过以下命令查看当前的默认设置:


make vars

如果你想改变这些文件夹的位置(比如你的系统盘快满了,想换到大容量机械硬盘上),可以按照以下步骤操作:

  • 第一步:创建配置文件。将项目目录下的 Batocera.mk.template 文件重命名为 Batocera.mk
  • 第二步:修改路径。打开该文件,找到 DL_DIR ?=(下载目录)和 OUTPUT_DIR ?=(产出目录)这两行,把等号后面的路径改为你心仪的位置。

生活化类比:这就像是装修房子。默认情况下,工人把材料堆在客厅(dl),把装好的家具摆在卧室(output)。如果你觉得太挤,可以给他们一张新的平面图(Batocera.mk),告诉他们把材料卸在仓库,成品搬到储藏室。

同时,这也是你决定为哪个平台“量身定制”系统的地方。例如,如果你想做最普通的“电脑版”系统,目标平台就是 x86_64


针对树莓派(Raspberry Pi)的镜像选择

如果你打算为树莓派系列编译系统,请根据你的硬件型号选择对应的镜像(Image)。这就好比你需要根据不同的车型选择不同的零配件:

镜像名称 (Image) 适用硬件 (Hardware)
broadcom/bcm2835 rpizero, rpizerow, rpi1A, rpi1B, rpi1A+, rpi1B+ (均为 32位)
broadcom/bcm2836 rpi2B, rpizero2W, rpi3B, rpi3A+, rpi3B+ (均为 32位)
broadcom/bcm2837 (待续)

【提示】:这些不同的型号代码代表了不同代际的树莓派处理器,选错了可能会导致编译出的系统无法在你的机器上启动。

硬件型号 (Hardware) 适用架构 (Architecture)
broadcom/bcm2837 rpizero2W, rpi3B, rpi3A+, rpi3B+ (均为 64位)
broadcom/bcm2711 rpi4B, pi400, cm4 (均为 64位)

【提示】:目前树莓派 3(RPi 3)的编译版本默认采用的是 64 位架构。


第五步:开始构建镜像

一切准备就绪后,就可以下达“开工”指令了。虽然针对不同的硬件架构(Target Architecture),命令略有不同,但它们都遵循统一的格式:make <架构名称>-build

  • 标准构建示例
    如果你要为普通电脑编译,请运行:

    make x86_64-build

  • 开启“多工模式”加速
    如果你拥有一颗核心数量超多的“神级”CPU,且内存也非常充裕,你可以开启并行构建(Parallel Build)来极大地缩短等待时间:

    PARALLEL_BUILD=1 make x86_64-build

生活化类比:普通构建就像是一个厨师在一个灶台上慢火细炖;而并行构建则像是雇了一群厨师,让所有灶台(CPU 核心)火力全开,同时炒好几个菜,出餐速度自然飞快。

【提示】:如果你不确定你的硬件对应哪个架构,可以再次运行 make vars 来查看所有有效的构建目标。

【注意】:每次构建新镜像时,output/<架构>/images 文件夹里的旧内容会被完全覆盖。镜像并不会随时间累积,如果你想保留某个特定版本,请务必在下一次编译前把它拷贝到其他地方。


第六步:进入交互式终端

有时候,你可能不想直接开始漫长的自动化编译,而是想钻进这个“虚拟车间”里手动调整一些参数。这时你可以进入交互式终端(Shell)环境。

  • 进入方式
    使用命令 make <架构名称>-shell,例如:

    make x86_64-shell

  • 配置内核(Kernel)
    进入交互式终端后,你可以调出功能强大的菜单配置工具(Menuconfig)。它提供了一个清晰的图形化界面,让你能像调整电视机设置一样,方便地配置 Linux 内核的各种选项:


make x86_64-shell


make menuconfig


第七步:编译单个软件包

如果你不想重新编译整个系统,而只想单独编译某一个特定的功能或驱动,可以使用 -pkg 命令或者在进入 Shell 后进行操作。

  • 第一步:指定架构与包名
    使用 make <架构>-pkg PKG=<包名> 的格式。例如,为 RK3326 平台编译开机画面:

    make rk3326-pkg PKG=Batocera-splash
  • 第二步:在 Shell 环境中编译
    你也可以先进入交互模式,再针对某个模拟器核心进行编译:

    make x86_64-shell PKG=libretro-MAME

【注意】:虽然这种方法能快速生成单个软件包,但它的运行环境与完整的 make x86_64-build 并不完全相同。如果你是为了测试某个包是否能编译成功并准备提交拉取请求,请务必使用 -build-cleanbuild 命令进行最终确认,以免出现“本地能过,合并就报错”的情况。


第八步:开启编译缓存加速

如果你经常需要反复编译,建议开启 CCache(编译器缓存)

生活化类比:这就像是你经常要做同样的数学题,CCache 会把算过的结果记在笔记本上。下次遇到同样的算式,你不需要重新计算,直接抄写答案(复用缓存)就行,速度提升非常明显。

  • 配置方法:你不需要去修改复杂的默认配置(defconfig),只需要在 Batocera.mk 文件中找到 EXTRA_OPTS 选项,按照模板示例添加相关的 CCache 参数即可。

第九步:执行“彻底清洗”编译

当你想要删除所有旧的数据,从零开始构建一个“纯净版”系统时,请使用 彻底清洗构建(Clean builds)。它会清空 output/<架构> 下的所有缓存和临时文件。

在以下场景中,这一步至关重要:
* 跨版本编译:如果你之前编译过新版 Batocera,现在想转而编译旧版本。
* 规避冲突:一定要做一次 cleanbuild。这能确保旧的构建缓存(Build cache)不会和旧版本的包发生冲突,避免产生那些让人摸不着头脑的错误提示。

生活化类比:这就像是重新装修房子。如果你只是小修小补,可能会发现旧的电线和新的插座不匹配。最稳妥的办法是把屋子彻底清空(Clean),然后再按新图纸重新装修。

为了保证编译过程万无一失,这里有几条关于“清洗构建”的生存法则。

  • 禁止“挑拣”代码(Cherry-picking):在 Batocera 的开发中,每一个提交(Commit)可能都依赖于之前的改动。这就像“多米诺骨牌”一样,即使看起来不相关的改动也可能互相关联。如果你曾经尝试过挑拣单个提交来编译,请务必执行 cleanbuild,否则后续可能会引发一连串莫名其妙的错误。
  • 版本切换必须清洗:如果你刚编译完一个旧版本,现在想切回最新版,请再次执行 cleanbuild。说实话,只有当你一直紧跟主分支(Master Branch)且从未改动过代码进行持续编译时,普通的构建命令才是绝对可靠的。
  • 解决“玄学”报错:当你遇到一些奇怪的报错,而其他开发者却没遇到时,或者当你的编译过程因为断电、手动停止而中断后,请直接祭出 cleanbuild 大法。

生活化类比:这就像是洗衣服。如果你只是日常穿着,简单洗洗就行(普通 Build);但如果你刚去泥地里滚了一圈(中断了编译)或者想把浅色衣服染成深色(切换版本),那就必须得来一次“深度干洗”(Cleanbuild),否则颜色肯定会染花。

运行以下命令来执行彻底清洗并开始构建:

make x86_64-cleanbuild


第十步:建立 Web 服务器来升级你的 Batocera

你可以非常方便地用刚刚编译好的成果来升级你的 Batocera 测试机。

假设你的编译机 IP 地址是 10.0.0.2。只要你的电脑上安装了 Python3,你就可以通过下面这条简单的指令化身为一台 Web 服务器(Webserver)


make x86_64-webserver

生活化类比:这相当于在你的电脑上开了一个“临时下载站”。你的 Batocera 游戏机可以直接通过网络访问这个站,像下载官方更新一样把你刚刚“手搓”出来的系统镜像拉过去安装。


第十一步:在测试机上执行升级

现在,回到你的 Batocera 游戏机上,通过控制台运行以下升级命令:


batocera-upgrade http://10.0.0.2:8000

【注意】:请确保你的编译机和 Batocera 游戏机处于同一个局域网内,并且防火墙没有拦截 8000 端口。

现在,你可以直接让你的 Batocera 测试机升级到刚“出炉”的系统版本了。

假设运行 Web 服务器的编译机 IP 地址是 10.0.0.10,你只需要通过 SSH 远程连接(Secure Shell) 登录到你的 Batocera 游戏机,然后输入以下命令:


batocera-upgrade http://10.0.0.10:8000


第十一步:清理陈旧的编译文件

随着时间的推移,Batocera 的各种包会不断更新。默认情况下,所有旧版本的源代码包和对应的二进制编译产物都会堆积在你的工作目录里。这就像是一个不断堆积杂物的车间,你需要定期打扫以腾出宝贵的存储空间。

生活化类比:这就像是你按照新菜谱做菜,但每次买回来的新食材(新源码)和做坏的半成品(旧构建文件)都堆在厨房里。如果你不扔掉那些过期的东西,很快你就连站脚的地方都没有了。

你可以通过以下指令来清理这些“过期物资”:

1. 清理下载目录(dl/)

  • 查看:找出 dl/ 目录中已经下载了更新版本、从而显得多余的旧包:

    make find-dl-dups
  • 删除:一键清除这些过时的下载包:

    make remove-dl-dups

2. 清理构建目录(build/)

  • 查看:以 x86_64 平台为例,查看构建树中哪些目录已经过时:

    make x86_64-find-build-dups
  • 删除:彻底移除这些不再需要的旧构建目录:

    make x86_64-remove-build-dups

【提示】:上面的命令中以 x86_64 为例,如果你编译的是其他平台,只需将架构名称替换为对应的即可(如 rpi4)。


第十二步:定位编译好的镜像文件

当你完成所有编译步骤后,最重要的成果——系统镜像(Image) 究竟在哪里呢?

(此处接原文后续关于镜像路径的说明)

第十二步:定位并使用编译好的镜像

如果你是在容器内部进行的操作,现在可以先退出容器了。

当你漫长的等待结束后,你亲手打造的“艺术品”——系统镜像(Image) 就在等着你了。

1. 镜像在哪里?

编译成功的成果会存放在 output/images/Batocera/images/<架构名称> 目录下。为了节省空间,这些镜像通常经过了 Gzip 压缩(Gzipped)

文件名会包含版本号、平台名称以及编译日期。
* 例如output/images/Batocera/images/x86_64/Batocera-x86_64-33-20220130.img.gz

2. 如何使用这个镜像?

你有多种方式来部署你的“新系统”:
* 常规烧录:参考官方安装说明,使用 Raspberry Pi Imager 或同类工具将镜像刷入存储介质。
* 网络升级:使用我们前面提到的 webserver 命令进行在线升级。
* 手动升级:手动替换系统分区文件。
* 命令行刷写:如果你是大神,也可以直接使用以下命令进行刷写(请务必将 TARGETDEVICE 替换为你真实的存储设备路径):

make DEV=/dev/TARGETDEVICE x86_64-flash


高级进阶技巧

编译参数微调(Building configuration)

你可以通过修改 Batocera.mk 文件中的选项,让编译过程更符合你的个人偏好。

【注意】:在修改配置文件时,每一行配置的前面必须保留一个空格字符。请千万不要删除这个前缀空格,否则会导致配置失效。

让电脑“喘口气”:调整编译压力

默认情况下,Docker 会像“吞噬者”一样,在编译时占用你电脑几乎所有的硬件资源。如果你想在编译的同时还能正常上网或处理文档,建议降低并行任务等级(MAKE_JLEVEL)

生活化类比:默认编译就像是请了一支装修队把家里所有的房间同时开工,虽然快,但你连坐的地方都没了。通过把 MAKE_JLEVEL 设为 1,就像是让工人一间一间地装,虽然慢一点,但你还能在剩下的房间里正常生活。

Batocera.mk 中修改如下代码:

MAKE_JLEVEL := 1

除了调整并行任务等级,你还可以通过将 并行构建(PARALLEL_BUILD) 参数设为 n 来彻底限制编译只使用单核处理器。

【注意】:虽然这样可以极大地减轻电脑负担,但代价是编译时间会大幅延长(甚至可能比平时慢 12 倍!)。


PARALLEL_BUILD := n


第十三步:管理你的硬盘空间

默认情况下,构建系统(Buildroot) 会利用缓存来存储最常用的编译函数。这能显著缩短重复编译的时间,但会占用额外的硬盘空间。

如果你的硬盘空间告急,可以通过在 EXTRA_OPTS 这一行后面添加参数来给缓存设置一个上限(例如限制在 50GB):


EXTRA_OPTS := BR2_CCACHE_INITIAL_SETUP="--max-size=50G"


第十四步:提前下载源码

为了让后续的编译过程更顺畅,你可以让电脑在正式动工前,先从互联网上把所有需要的原材料都下载好。以 x86_64 平台为例,运行:


make x86_64-source

资深编辑的小贴士:我个人的习惯是先让这个下载命令跑上 10 分钟,确保大头文件都到位了,再开启并行编译。


第十五步:查看编译进度

编译是一个漫长的过程,如果你想看看你的 x86_64 构建任务进行到哪一步了,可以查看编译日志(Build-time log)


tail -f output/x86_64/build/build-time.log

生活化类比:这就像是盯着烤箱里的温度计。虽然你不需要手动操作,但通过观察这个不断滚动的日志,你可以实时确认“这锅菜”有没有烧糊。


第十六步:还有哪些没编译完?

如果你之前运行过 make source 命令,想快速找出还有哪些包排队等着编译,可以运行:


make x86_64-show-build-order

如果你之前运行过源码下载命令,想看看还有多少“硬骨头”没啃完,可以运行下面这段脚本。它会扫描并列出所有还没打上“编译完成”戳记的文件夹,并统计剩余数量:


for i in output/x86_64/build/*; do test -d "$i" && test -e "$i"/.stamp_built || echo "$i"; done | tee /dev/tty | wc -l


第十七步:Docker 高级维护技巧

为了让你的编译环境保持高效和整洁,这里有一些实用的 Docker 管理指令。

1. 共享下载目录

如果你有多个版本的 Batocera 源码,为了避免重复下载相同的包,你可以让所有构建任务共享同一个下载文件夹(比如你家目录下的 DL 文件夹):


docker run -it --rm -v $PWD:/build -v $HOME/dev/Batocera/DL:/build/dl Batocera-docker

生活化类比:这就像是你有多个装修工地,但大家共用一个大仓库。这样就不用给每个工地都买一份同样的建材,既省钱(省带宽)又省地方(省硬盘)。

2. 管理镜像与容器

镜像(Image)是环境的模板,而容器(Container)是正在运行的实例。

  • 查看已有的镜像:看看你的电脑里存了哪些环境模板。

    docker image ls
  • 更新镜像:保持你的编译工坊工具处于最新状态。

    make update-docker-image
  • 删除镜像:如果你不再需要某个旧环境,可以手动清理它。

    docker rmi <镜像名称> # 或者使用 docker image rm <镜像名称>
  • 查看正在运行的任务:列出当前活跃的 Docker 容器。

    docker ps
  • 强制停止任务:如果编译卡死或你想强行中断。

    docker kill [容器名称]

第十八步:常见问题排查(Tips)

1. 了解目录结构

如果你打算修改系统功能,建议深入了解 Batocera 源码的层级结构,这样你才能找准修改代码的位置。

2. Ubuntu Docker 中的 qt5base 编译错误

如果你在 Ubuntu 环境下的 Docker 中遇到了 qt5base 编译失败,可以尝试以下两种方案:
* 在 Docker 运行命令中添加参数:--security-opt seccomp:unconfined
* 或者更新宿主机的 libseccomp2 软件包。

【提示】:自 2020 年 2 月起,这个问题似乎已经得到了修复,通常不再需要手动处理。

3. 在 LXC 容器中编译

如果你选择在 LXC 容器(LinuX Containers) 环境中编译 Batocera…

如果你偏好使用 LXC 容器(LinuX Containers) 环境进行编译,可以参考专门的“在 LXC 容器中编译”页面来获取详细的操作指南。


第十九步:跳过特定软件包的编译

在漫长的编译过程中,你可能会遇到某个软件包因为各种原因导致编译失败。如果你不想卡在这里,而是想先去测试后面的包是否正常,可以采取“跳过”策略。

1. 临时跳过(伪造成功证明)

你可以通过手动创建该软件包的戳记文件(Stamp files),来蒙蔽编译系统,让它以为这个包已经成功构建完成了。

2. 永久跳过(修改配置文件)

如果你想更彻底、更方便地跳过某个包,可以直接从主包的 Config.in 配置文件中抹除它的名字。

生活化类比:这就像是一份“必修课清单”。如果你发现某门课(软件包)实在修不过去,又不想耽误拿毕业证,你可以直接从教学大纲(Config.in)里把这门课删掉(注释掉),这样学校(编译系统)就不会再要求你必须完成它了。

操作示例:
例如,如果你想在编译时跳过 PCSX2 独立模拟器及其 Libretro 核心,只需找到 package/Batocera/core/Batocera-system/Config.in 文件,并在对应的行前面加上 # 号进行注释(Comment out)

select BR2_PACKAGE_PCSX2 if BR2_PACKAGE_BATOCERA_TARGET_X86_64

select BR2_PACKAGE_PCSX2_AVX2 if BR2_PACKAGE_BATOCERA_TARGET_X86_64

select BR2_PACKAGE_LIBRETRO_PCSX2 if BR2_PACKAGE_BATOCERA_TARGET_X86_64


第二十步:定义特定平台的 Buildroot 配置

(此处接原文后续关于如何为特定硬件平台自定义 Buildroot 详细配置的说明)

假设你打算为树莓派 3(Raspberry Pi 3)编译系统。你可以通过以下步骤来刷新该平台的 Buildroot 默认配置(Buildroot configuration)

第二十步:定义特定平台的 Buildroot 配置

  • 第一步:生成配置文件
    运行以下命令:

    make Batocera-rpi3_defconfig

    执行后,系统会根据 configs/Batocera-rpi3_defconfig 里的模板,在当前目录下生成一个名为 .config 的文件。

  • 第二步:重置配置(可选)
    如果你为了测试或开发手动修改了 .config 文件,但现在想反悔了,只需再次运行 make Batocera-rpi3_defconfig,它就会像“一键还原”一样把配置重置回初始状态。

配置文件的“套娃”逻辑

为了让你更清楚这两个文件的关系,我们可以做一个类比:

生活化类比Batocera-rpi3_defconfig 就像是一张极简购物清单,上面只写了你最想要的几样大件,比如“Kodi 播放器”和“EmulationStation 游戏前端”。

而生成的 .config 文件则是最终的结账清单。它非常详尽,不仅包含了你要的大件,还自动补全了所有赠品和配件(依赖包)。

比如你只想买“EmulationStation”,但它必须配合“SDL2”才能跑起来。那么在极简清单里你只看得到前者,但在最终的 .config 结账单里,你会发现两者都被勾选为了“Yes”(例如 BR2_PACKAGE_BATOCERA_EMULATIONSTATION=y)。


第二十一步:故障排查(Troubleshooting)

Docker 权限不足导致无法开始编译

如果你选择在 Docker 环境下进行编译,必须确保你的当前用户已经加入了 docker 用户组。

【注意】:如果没有这个权限,Docker 就像是一个锁死的车间大门,无论你输入多少编译指令,系统都会因为“查无此人”而拒绝开工。请参考前文“配置 Docker 环境”部分,确保权限设置正确。

如果你无法成功将用户加入 Docker 组,这里有一个临时的应急方案:直接在命令前加上 sudo提权(Elevated privileges)运行,例如 sudo make x86_64-build

【注意】:虽然这能解决权限报错,但由于安全和系统稳定性的显而易见的原因,官方强烈不建议在日常操作中这样做。


1. 忽略本地的 Batocera.mk 配置文件

如果你在本地修改了 Batocera.mk,但又不想在提交代码时让 Git 版本控制(Git repo) 追踪到这个文件的变化,你可以运行以下命令让 Git 假装“看不见”它的改动:


git update-index --assume-unchanged Batocera.mk


2. 在应用 Linux 内核补丁时,编译突然中断

这种情况通常是因为文件夹里的 Linux 内核(Linux kernel) 源码不完整,或者是之前的编译过程被迫中止导致的。

生活化类比:这就像是在盖房子时,地基只打了一半就停工了,导致后续的钢筋架子(补丁)怎么也搭不上。最简单的办法就是把这块烂尾的地基铲掉重建。

要修复这个问题,请执行以下步骤:
* 第一步:进入编译环境的终端:

make x86_64-shell

* 第二步:删除旧的内核构建目录:

rm -rf build/Linux-*

【提示】:这个方法同样适用于“修复”任何在编译中途被打断的软件包。比如编译到一半时突然停电了,或者电脑意外重启,你都可以通过这个方法清理掉受损的中间文件。


3. 编译在随机的时间点莫名停止

如果编译过程在没有明确报错的情况下突然中断,请尝试以下操作:

  • 第一步:更新环境。首先务必确认你已经更新了最新的 Docker 镜像,确保你的“工具箱”是最新的。
  • 第二步:检查资源。确认你的内存或磁盘空间没有被耗尽。

编译中断可能会在任何时候发生,通常与某个特定的模拟器包有关。在每一个包的输出目录 output/build/<包名>-<版本号> 下,都藏着一些戳记文件(Stamp files),它们记录了编译进行到了哪一步。

常见的“进度戳记”包括:
* 下载(Download)
* 解压(Extract)
* 补丁(Patch)
* 配置(Configure)
* 构建(Built)
* 中间层安装(Staging_install)
* 目标安装(Target_install)

生活化类比:这就像是在跑马拉松,每到一个补给站,裁判就会在你的手册上盖一个章(.stamp)。如果比赛中途停止了,裁判看一眼手册上的章,就知道你最后跑到了哪一个里程碑。

当你识别并解决了导致中断的问题后,你可以通过删除对应的构建文件夹来让这个包重新开始编译。

4. 手动“盖章”或重置故障包

假设你在编译 bsnes 模拟器时遇到了麻烦,但你认为构建和安装已经基本完成了,你可以手动为它“盖章”跳过这些步骤:

  • 第一步:手动标记完成
    你可以使用 touch 命令生成伪装的戳记文件:

    touch ~/Batocera.Linux/output/x86_64/build/libretro-bsnes-hd-0fd18e0f5767284fd373aebd75b00b5bab0d44a9/{.stamp_built,.stamp_target_installed}

  • 第二步:彻底重跑单项编译
    如果你想让这个包彻底重来,以确定是这个包本身有问题还是整个 Batocera 环境的问题,请执行以下操作:

    # 删除旧的构建文件夹
    rm -rf ~/Batocera.Linux/output/x86_64/build/libretro-bsnes-hd-0fd18e0f5767284fd373aebd75b00b5bab0d44a9
    # 重新单独编译该包
    make libretro-bsnes-hd

3. 编译随机中断,且使用戳记法(Stamps)也无法查明原因

如果你发现编译还是莫名其妙地停下来,即便检查了进度戳记也毫无头绪,那很可能是因为下载的代码已经损坏或版本过旧。

生活化类比:这就像是你按照一张被墨水打湿、字迹模糊的图纸盖房子,无论你怎么修补,最后总会出问题。最省心的办法就是把旧图纸扔了,直接进行一次“彻底清洗构建(Clean build)”。

运行以下命令,从头开始干净利落地构建:

make <目标平台>-cleanbuild


4. 软件包下载地址失效(报错 404 Error)

编译时,如果系统提示某个软件包的下载链接失效了(404 Not Found),你可以采取“手动搬运”的应急方案。

第一步:手动下载包
找到那个报错的软件包,手动将其下载到本地。

第二步:放入对应的下载目录(dl/)
将下载好的文件放到 dl/<包名> 文件夹下。
例如:如果软件包 xa-2.3.11.tar.gz 报错 404,你就手动下载它,然后按照下面的结构摆放:


Batocera.Linux/
└─ dl/
└─ xa/
└─ xa-2.3.11.tar.gz


5. 编译 x86_64 时遇到 Wine 相关的 404 错误

当你尝试编译全新的 Batocera 版本时,可能会遇到这个问题。Batocera 的 GitHub 仓库通常会托管一个巨大的 Wine/Wow64 预编译包(wine-x86-<版本>.tar.lzma)。如果官方还没来得及上传你正在编译的那个版本,系统就会报错 404。

修复步骤:
1. 在你的构建树中运行:make x86_wow64-cleanbuild
2. 将生成的包手动移动到你的 dl/wine-x86/ 目录下即可。

【提示】:这属于版本更新初期的常见现象,手动“搬运”一下生成的包就能绕过这个坎。

6. Docker 编译时下载工具(Wget)无响应

有时候在 Docker 容器里下载文件,Wget 工具会像断了网一样卡住不动。这通常是因为容器内部的 最大传输单元(MTU) 与你宿主机的设置不一致导致的。

生活化类比:这就像是你家大门口的限高是 2 米(宿主机 MTU),但你院子里的卡车却装了 3 米高(Docker MTU)。车子在院里跑得欢,可一到大门口就卡死,货物(数据包)自然发不出去也收不到。

修复步骤:
* 第一步:查看 MTU 值。在宿主机终端输入 ifconfigip a,检查物理网卡和 Docker 网卡的 MTU 数值。
* 第二步:匹配数值。如果你使用了虚拟专用网(如 Wireguard),其 MTU 可能低于默认的 1500(例如是 1420)。
* 第三步:修改 Docker 配置。编辑或创建 /etc/docker/daemon.json 文件,将 Docker 的 MTU 改为与系统一致:


{
"mtu": 1420
}


7. 编译后出现了一堆被修改的 .po 文件

你可能发现自己明明没动过语言包,但编译完后,Git 提示一堆 多语言翻译文件(.po) 被修改了。

别担心,这是正常现象:
这种情况通常是因为之前有人在合并代码前没运行编译,导致这些翻译文件“过期”了。一旦你运行编译,系统会自动更新它们。

处理建议:
* 如果你提交的代码里没有涉及新的文字字符串,直接丢弃(Discard)掉对这些 .po.pot 文件的修改即可。
* 当然,把它们一起提交也没问题,反正下次主分支编译时它们还是会被更新。

【注意】:这里有一个特别需要留心的地方。如果主分支(Master Branch)在合并时没有经过编译,且恰好有翻译人员非常高效地为新加入的字符串提供了翻译,那么你编译时自动生成的 PO 文件可能会覆盖掉人家辛苦翻译好的内容。

在这种特定情况下,你“必须丢弃”这些 PO 文件的修改,而不是“随意丢弃”。


8. 编译成功了,但我改动的代码没生效?

如果你发现编译过程顺顺利利地跑完了,但你对代码做的修改在最终成品里完全没影,这通常是因为 构建系统(Buildroot) 认为这个包已经“做好了”。

生活化类比:这就像是你去餐厅点了一份改了配方的炒饭,但厨师看后厨里还有一份刚才炒好、还没卖出去的普通炒饭,就直接把它端给了你(复用旧的构建结果),而没去管你新提的要求。

解决方法:
如果软件包的版本号没变,且 output/<架构>/build/<包名> 文件夹依然存在,系统就会跳过重新构建。你只需要手动把这个文件夹删掉,就能强制系统重新“开火”编译。

  • 操作示例
    如果你为了添加新系统而修改了 es_systems.yml 文件,那么你需要执行以下操作:

第一步:找到并删除旧的构建文件夹

rm -rf output/<架构>/build/Batocera-configgen

第二步:重新开始编译
再次运行你的编译命令,系统就会因为找不到旧文件夹而乖乖按照你修改后的代码重新构建了。


原文: 从源码编译Batocera • 翻译: DIY8 Bot

© 版权声明
评论 抢沙发

请登录后发表评论

    暂无评论内容