跳到主要内容

Dockerfile构建riscv-gnu-toolchain镜像

elf-gcc

基于ubuntu 22.04构建

vim Dockerfile
# 使用官方的 Ubuntu 22.04 镜像作为基础镜像
FROM ubuntu:22.04

# 设置镜像的维护者信息
LABEL maintainer="qymlyl"

# 用户默认是root,目录默认是/,WORKDIR设置默认的工作目录
WORKDIR /opt/source

# 运行更新命令以获取最新的软件包列表并安装必要的工具
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y openssh-server vim autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libpixman-1-0 libpixman-1-dev

# clone riscv-gun-tool及子模块
RUN curl https://mirror.iscas.ac.cn/riscv-toolchains/git/riscv-collab/riscv-gnu-toolchain.sh | bash

# 编译riscv-gnu-toolchain
# --enable-multilib:构建支持 32 位和 64 位的交叉编译器
RUN cd riscv-gnu-toolchain && \
./configure --prefix=/opt/riscv --enable-multilib && \
make -j$(nproc) && \
make -j$(nproc) build-sim SIM=qemu QEMU_TARGETS=riscv64-linux-user,riscv32-linux-user,riscv64-softmmu,riscv32-softmmu

# 设置 RISCV变量
RUN echo 'export RISCV=/opt/riscv' >> /etc/profile && \
echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile && \
/bin/bash -c 'source /etc/profile' && \
echo 'export RISCV=/opt/riscv' >> ~/.bashrc && \
echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc && \
/bin/bash -c 'source ~/.bashrc'

# 将默认工作目录设置在/
WORKDIR /

# 删除源码
RUN rm -rf /opt/source

# 定义容器启动时运行的命令
CMD ["bash"]

构建镜像

# 构建新的版本时注意清除构建缓存
docker builder prune
# 基于amd64 ubuntu22.04镜像构建的支持riscv64和riscv32两种架构的elf-gcc和qemu
# 拉取的是官方最新的代码
# 这里对应官方2024/7/3的提交, commitid: 1358115963fb55cc445535d8a931e2f51dbe1940
nohup docker build -t riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115 . &

镜像压缩

# 未压缩之前20G(包含源码层),压缩后2G
docker-squash riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115 \
-t riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115_squashed

glibc-gcc

基于ubuntu 22.04构建

# 使用官方的 Ubuntu 22.04 镜像作为基础镜像
FROM ubuntu:22.04

# 设置镜像的维护者信息
LABEL maintainer="qymlyl"

# 用户默认是root,目录默认是/,WORKDIR设置默认的工作目录
WORKDIR /opt/source

# 运行更新命令以获取最新的软件包列表并安装必要的工具
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y openssh-server vim autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libpixman-1-0 libpixman-1-dev

# clone riscv-gun-tool及子模块
RUN curl https://mirror.iscas.ac.cn/riscv-toolchains/git/riscv-collab/riscv-gnu-toolchain.sh | bash

# 编译riscv-gnu-toolchain
# --enable-multilib:构建支持 32 位和 64 位的交叉编译器
RUN cd riscv-gnu-toolchain && \
./configure --prefix=/opt/riscv --enable-multilib && \
make linux -j$(nproc) && \
make -j$(nproc) build-sim SIM=qemu QEMU_TARGETS=riscv64-linux-user,riscv32-linux-user,riscv64-softmmu,riscv32-softmmu

# 设置 RISCV变量
RUN echo 'export RISCV=/opt/riscv' >> /etc/profile && \
echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile && \
/bin/bash -c 'source /etc/profile' && \
echo 'export RISCV=/opt/riscv' >> ~/.bashrc && \
echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc && \
/bin/bash -c 'source ~/.bashrc'

# 将默认工作目录设置在home目录
WORKDIR /

# 定义容器启动时运行的命令
CMD ["bash"]

构建镜像

# 构建新的版本时注意清除构建缓存
docker builder prune
nohup docker build -t riscv-gnu-toolchain:glibc_gcc_qemu_HEADE_1358115 . &

镜像压缩

# 未压缩之前20G(包含源码层),压缩后2G
docker-squash riscv-gnu-toolchain:glibc_gcc_qemu_HEADE_13581155 \
-t riscv-gnu-toolchain:glibc_gcc_qemu_HEADE_1358115_squashed

musl-gcc

基于ubuntu 22.04构建

# 使用官方的 Ubuntu 22.04 镜像作为基础镜像
FROM ubuntu:22.04

# 设置镜像的维护者信息
LABEL maintainer="qymlyl"

# 用户默认是root,目录默认是/,WORKDIR设置默认的工作目录
WORKDIR /opt/source

# 运行更新命令以获取最新的软件包列表并安装必要的工具
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y openssh-server vim autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libpixman-1-0 libpixman-1-dev

# clone riscv-gun-tool及子模块
RUN curl https://mirror.iscas.ac.cn/riscv-toolchains/git/riscv-collab/riscv-gnu-toolchain.sh | bash

# 编译riscv-gnu-toolchain
# --enable-multilib:构建支持 32 位和 64 位的交叉编译器(对于mul并没有起作用,mul只支持64位架构)
RUN cd riscv-gnu-toolchain && \
./configure --prefix=/opt/riscv --enable-multilib && \
make musl -j$(nproc) && \
make -j$(nproc) build-sim SIM=qemu QEMU_TARGETS=riscv64-linux-user,riscv32-linux-user,riscv64-softmmu,riscv32-softmmu

# 设置 RISCV变量
RUN echo 'export RISCV=/opt/riscv' >> /etc/profile && \
echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile && \
/bin/bash -c 'source /etc/profile' && \
echo 'export RISCV=/opt/riscv' >> ~/.bashrc && \
echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc && \
/bin/bash -c 'source ~/.bashrc'

# 将默认工作目录设置在home目录
WORKDIR /

# 定义容器启动时运行的命令
CMD ["bash"]

构建镜像

# 构建新的版本时注意清除构建缓存
docker builder prune
nohup docker build -t riscv-gnu-toolchain:musl_gcc_qemu_HEADE_1358115 . &

镜像压缩

docker-squash riscv-gnu-toolchain:musl_gcc_qemu_HEADE_1358115 -t riscv-gnu-toolchain:musl_gcc_qemu_HEADE_1358115_squashed

启动示例

以elf_gcc为例

创建容器

# riscv toolchain是基于ubuntu 22.04镜像进行构建,这里设置一个端口与22端口进行映射便于使用ssh链接
docker run --name riscv64_elf_gcc \
-p 10022:22 \
-itd mqylyl/riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115

进入容器

docker exec -it riscv64_elf_gcc /bin/bash

查看版本信息

$ riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/opt/riscv/libexec/gcc/riscv64-unknown-elf/13.2.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with: /opt/source/riscv-gnu-toolchain/gcc/configure --target=riscv64-unknown-elf --prefix=/opt/riscv --disable-shared --disable-threads --enable-languages=c,c++ --with-pkgversion=gc891d8dc23e --with-system-zlib --enable-tls --with-newlib --with-sysroot=/opt/riscv/riscv64-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --enable-multilib --with-abi=lp64d --with-arch=rv64imafdc --with-tune=rocket --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (gc891d8dc23e)
$ qemu-system-riscv64 -version
QEMU emulator version 8.1.1 (v8.1.1)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers

编译运行C程序(hello_world.c)

编写hello_world.c文件

echo '#include <stdio.h>' > hello_world.c && \
echo 'int main() {' >> hello_world.c && \
echo ' printf("Hello, world!\n");' >> hello_world.c && \
echo ' return 0;' >> hello_world.c && \
echo '}' >> hello_world.c

编译运行riscv64

# 编译
$ riscv64-unknown-elf-gcc -march=rv64imafdc -mabi=lp64 -o hello_world_64 hello_world.c

# 查看二进制文件格式,64-bit
$ file hello_world_64
hello_world_64: ELF 64-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped

# 使用qemu运行程序
# qemu-riscv64:user mode运行
# -L: 用于加载模拟器的体系结构支持文件的目录(risc-v的一些库都在$RISCV/sysroot目录下)
# qemu-riscv64 -L $RISCV/sysroot ./hello_world_64
$ qemu-riscv64 ./hello_world_64
hello world!

编译运行riscv32

# 编译
$ riscv64-unknown-elf-gcc -march=rv32imafdc -mabi=ilp32 -o hello_world_32 hello_world.c

# 查看二进制文件格式,32-bit
$ file hello_world_32
hello_world_32: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not strippe

# 运行
$ qemu-riscv32 ./hello_world_32
hello world!

二进制程序和源码目录

二进制程序放在在/opt/riscv

问题

镜像太大了

$ docker images riscv-gnu-toolchain:riscv6432_elf_gcc_qemu_20231018_nightly_ubuntu2204_arm64
REPOSITORY TAG IMAGE ID CREATED SIZE
riscv-gnu-toolchain riscv6432_elf_gcc_qemu_20231018_nightly_ubuntu2204_arm64 e272d8d35157 About an hour ago 22.1GB
$ docker history riscv-gnu-toolchain:riscv6432_elf_gcc_qemu_20231018_nightly_ubuntu2204_arm64
IMAGE CREATED CREATED BY SIZE COMMENT
e272d8d35157 About an hour ago CMD ["bash"] 0B buildkit.dockerfile.v0
<missing> About an hour ago WORKDIR / 0B buildkit.dockerfile.v0
<missing> About an hour ago RUN /bin/sh -c echo 'export RISCV=/opt/riscv… 3.79kB buildkit.dockerfile.v0
<missing> About an hour ago RUN /bin/sh -c cd riscv-gnu-toolchain &&12.1GB buildkit.dockerfile.v0
<missing> 7 hours ago RUN /bin/sh -c curl https://mirror.iscas.ac.… 9.42GB buildkit.dockerfile.v0
<missing> 9 hours ago RUN /bin/sh -c apt-get update && apt-get… 528MB buildkit.dockerfile.v0
<missing> 9 hours ago WORKDIR /opt/source 0B buildkit.dockerfile.v0
<missing> 9 hours ago LABEL maintainer=qymlyl 0B buildkit.dockerfile.v0
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:f8594e26831508c31… 69.2MB
<missing> 3 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ARG RELEASE 0B

source: not found

 > [6/6] RUN echo 'export RISCV=/opt/riscv' >> /etc/profile &&     echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile &&     source /etc/profile &&     echo 'export RISCV=/opt/riscv' >> ~/.bashrc &&     echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc &&     source ~/.bashrc:
0.296 /bin/sh: 1: source: not found
------

解决方案:使用/bin/bash -c source

Dependency "pixman-1" not found

编译Qemu时遇到

un-time dependency pixman-1 found: NO (tried pkgconfig)

../qemu/meson.build:840:11: ERROR: Dependency "pixman-1" not found, tried pkgconfig

A full log can be found at /home/parallels/Wokspace/study/riscv/riscv-gnu-toolchain/build-qemu/meson-logs/meson-log.txt

ERROR: meson setup failed

make: *** [Makefile:903: stamps/build-qemu] Error 1

解决方案:

sudo apt-get install libpixman-1-0 libpixman-1-dev