背景
在尝试通过源码编译 Anbox snap 的时候,遇到了以下错误:
Failed to fetch stage packages: Error downloading packages for part 'anbox': The package 'libboost-thread1.58.0' was not found
The linker version '2.23' used by the base 'core' is incompatible with files in this snap:
通过搜索引擎了解到,libboost-thread1.58.0
等包只在 Ubuntu 16.04 及以前版本的软件源中提供,而在我的机器上安装的 Ubuntu 18.04 LTS 所使用的软件源中已经不再提供,取而代之的是 libboost-thread1.65.1
以及 libboost-thread1.62.0
。另外查看 anbox 在 snapcraft.io 提供的在线构建服务的构建日志,发现其中的编译环境是 Ubuntu 16.04,也就是说 Ubuntu 16.04 应该是可以进行 Anbox snap 构建的环境。
在关于 snapcraft 与 linker version 的搜索结果中了解到 snapcraft 有一个叫做 cleanbuild 的功能,可以在一个 lxd 容器(默认选择 Ubuntu 16.04 环境)中进行 snapcraft 构建,从而解决依赖缺失、linker 版本不符等问题。但是在尝试使用 snapcraft cleanbuild 的过程中遇到了诸多琐碎的小问题,最终是未能成功完成构建。后来想到在我目前使用的系统中已经装有 Docker,也可以提供特定版本的干净环境用于构建,于是尝试在 Docker 中进行并完成了 snapcraft 的构建操作,以下是此方案的一系列步骤记录。
环境
- 安装并配置好 Docker
- (可选)当前用户已加入
docker
组(以便在执行docker
的相关命令时不需要加上sudo
)
容器准备
既然要使用 Docker,那么第一步自然是要决定使用何种容器。有以下两种选择:
- ubuntu:16.04
- snapcore/snapcraft:stable
查看 snapcore/snapcraft
的 dockerfile
,发现其基础镜像为 ubuntu:xenial
(也就是 Ubuntu 16.04),在其中已经安装配置好了 snapcraft。方便起见,直接选择 snapcore/snapcraft:stable
这一镜像进行后续步骤。
操作:执行以下命令拉取镜像。
$ docker pull snapcore/snapcraft:stable
环境配置与调整
以下假设:
- 要执行
snapcraft
的项目目录在宿主机的路径为/path/to/project_dir/
下述命令将完成以下配置:
- 将
/path/to/project_dir/
挂载到容器的/build
目录,以供构建 - 设置容器的工作目录为
/build
,以便操作便利 - 设置容器名称为
snapcraft
,以便进行后续操作
操作:执行以下命令配置并启动容器,进入容器的 Shell。
$ docker run -it \
-v /path/to/project_dir/:/build \
-w /build \
--name snapcraft \
snapcore/snapcraft:stable
默认的 ubuntu:xenial
镜像使用的 APT 源为 http://archive.ubuntu.com/
,不带根据地区的自动重定向且服务器位于英国,软件包下载较慢。考虑到构建过程中需要下载诸多依赖的软件包,在进行 snapcraft 之前需要对此进行更改。
考虑以下情况:
- 由于镜像里面缺文本编辑器(没有
vi
),所以简单使用echo
以及输出重定向以修改/etc/apt/sources.list
文件。 - 由于镜像里面没有 APT 的 HTTPS 支持(没有
apt-transport-https
),所以先切换到国内的清华镜像源(HTTP),安装apt-transport-https
以后再切换到 HTTPS 镜像源。(当然也可以直接使用 HTTP 的镜像源。
操作:执行以下命令将 APT 软件源切换到清华镜像源(HTTP),并更新软件包列表。
# echo -e "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse\ndeb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse" > /etc/apt/sources.list
# apt-get update
操作(可选但建议):执行以下命令安装 apt-transport-https
,将 APT 软件源切换到清华镜像源(HTTPS),并更新软件包列表。
# apt-get install apt-transport-https
# echo -e "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse" > /etc/apt/sources.list
# apt-get update
进行构建
操作:
# snapcraft
然后耐心等待构建完成。
整理
操作:退出容器的 Shell,关闭容器,然后删除容器(如有需要,可以保留该容器以备再次使用)。
# exit
$ docker stop snapcraft
$ docker rm snapcraft
由于容器内是以 root
身份执行 snapcraft
的,因此在构建过程中创建的文件的 owner 也为 root
。
操作:执行以下命令重新获得项目目录下的文件的所有权。(注:$USER
为环境变量,其值为当前登录的用户名,可以不作改动)
$ sudo chown -R $USER:$USER $PROJECT_PATH
参考资料
本文采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
本文作者:KeNorizon
本文链接:http://kenorizon.cn/solution/snapcraft-build-on-docker.html
评论