在Docker中使用crosstool-ng构建交叉编译工具链
最近开始接触嵌入式Linux,构建嵌入式Linux相关的 程序如U-Boot、Kernel等需要在开发主机上安装交叉 编译工具链,本文记录一次在Docker中使用crosstool-ng 构建设适用于 TI Sitara AM3358 SOC 交叉编译工具链的过程。
相关背景
1. crosstool-ng
crosstool-ng用于构建交叉编译工具链,通过一套菜单化配置界面 (menuconfig)使开发者可以以自动化的方式生成适用于不同架构与 C库的交叉编译环境,省去手动编译 binutils、GCC、glibc 等组件 的麻烦。
2. 为什么使用Docker
最开始,我尝试在主机的 Arch Linux 系统上直接使用 crosstool-ng 构建交叉编译工具链,但最终以失败告终。原因在于 crosstool-ng 对构建环境的依赖非常严格,而 Arch Linux 的软件版本普遍较新, 常常与 crosstool-ng 期望的工具链构建流程不完全兼容。
实际操作下来,我发现折腾环境的时间已经远超过“构建工具链”本身。 因此,为了获得一个干净、稳定、可重复的构建环境,最终选择了使用 Docker。 通过 Docker,可以轻松创建一个稳定的 Ubuntu 22.04 环境, 并在其中顺利构建所需的交叉编译工具链。
实验环境
- 主机OS: Arch Linux
- 开发板: BeagleBone Black
Docker容器创建
以下Dockerfile和脚本文件的编写参考了 https://github.com/nxp-imx/imx-docker
1. Dockerfile
FROM ubuntu:22.04
# Update system and add the packages required for crosstool-ng builds.
# Use DEBIAN_FRONTEND=noninteractive, to avoid image build hang waiting
# for a default confirmation [Y/n] at some configurations.
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev \
python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip \
patch libstdc++6 rsync git meson ninja-build locales sudo vim curl iputils-ping \
libssl-dev libgnutls28-dev net-tools
# Set up locales
RUN locale-gen en_US.UTF-8 && \
update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
# Needs 'source' command for setting up the build environment, so replace
# the 'sh' alias to 'bash' instead of 'dash'.
RUN rm /bin/sh && ln -s bash /bin/sh
# Add your user to sudoers to be able to install other packages in the container.
ARG USER
RUN echo "${USER} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER} && \
chmod 0440 /etc/sudoers.d/${USER}
# Set the arguments for host_id and user_id to be able to save the build artifacts
# outside the container, on host directories, as docker volumes.
ARG host_uid \
host_gid
RUN groupadd -g $host_gid ctng && \
useradd -g $host_gid -m -s /bin/bash -u $host_uid $USER
# Builds should run as a normal user.
USER $USER
ARG DOCKER_WORKDIR
WORKDIR ${DOCKER_WORKDIR}
2. Docker镜像/容器操作相关脚本
为了方便Docker镜像构建和启动容器等操作,编写了一系列脚本:
env.sh
DOCKER_IMAGE_TAG="ctng"
DOCKER_WORKDIR=$YOUR_WORKDIR
CTNG_RELEASE="crosstool-ng"
docker-build.sh
. ./env.sh
usage() {
echo -e "\e[3m\nUsage: $0 [path_to_Dockerfile]\e[0m\n"
}
if [ $# -ne 1 ]
then
usage
else
docker build --tag "${DOCKER_IMAGE_TAG}" \
--build-arg "DOCKER_WORKDIR=${DOCKER_WORKDIR}" \
--build-arg "USER=$(whoami)" \
--build-arg "host_uid=$(id -u)" \
--build-arg "host_gid=$(id -g)" \
-f $1 \
.
fi
docker-run.sh
. ./env.sh
docker run -it --rm \
# use '-e' or '--env' here to set environment variables within the container
# such as http/https proxies.
--volume ${HOME}:${HOME} \
--volume ${DOCKER_WORKDIR}:${DOCKER_WORKDIR} \
--volume ${DOCKER_WORKDIR}/${CTNG_RELEASE}:${DOCKER_WORKDIR}/${CTNG_RELEASE} \
"${DOCKER_IMAGE_TAG}" \
$1
3. 构建Docker镜像并启动容器
./docker-build.sh Dockerfile
./docker-run.sh
构建交叉编译工具链
以下操作均在Docker容器下执行。
1. 构建crosstool-ng
git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
./bootstrap
./configure --enable-local
make
2. 配置待构建工具链
注意工作路径,应该位于env.sh中配置的DOCKER_WORKDIR下。
查看crosstool-ng提供的构建配置文件
crosstool-ng/ct-ng list-samples
加载配置文件
使用与目标平台(Sitara AM3358) 最接近的 Cortex A8 样例配置:
crosstool-ng/ct-ng arm-cortex_a8-linux-gnueabi
调整配置
进入菜单化配置界面:
crosstool-ng/ct-ng menuconfig
做了如下调整:
Target选项中,Use specific FPU设置为vfpv3,Floating point设置为hardware (FPU)Toolchain选项中,Tuple's vendor string设置为unknownOperating System中,Version of linux选择6.12Debug facilities下所有的项目取消选择- 其余配置选项保持crosstool-ng预设的默认值
3. 构建工具链
执行:
crosstool-ng/ct-ng build
构建工具链,构建完成后,工具链默认安装在$HOME/x-tools/路径下。