Skip to content

Commit e9d1f05

Browse files
0ndorioctron
authored andcommitted
Reorganize Dockerfile and update scripts.
As the xtensa-esp32-rust toolchain contains multiple components which all require their own setup the Dockerfile is rather large. To increase the maintainability the file got reorganized. The updated Dockerfile should ... - expose the expected versions of the toolchain components, - add a bit more structure to the final container, - avoid to build and run the llvm tests - remove unnecessary intermediate artefacts before they are persisted, - and replace xargo which is in maintanence mode with cargo-xbuild. To reflect these changes the scripts got updated as well and all shellcheck related warnings got fixed. Also a new `flash-project` executable got added which can be used to flash the image to `/dev/ttyUSB0`.
1 parent 5925c4b commit e9d1f05

File tree

9 files changed

+216
-107
lines changed

9 files changed

+216
-107
lines changed

Dockerfile

Lines changed: 155 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,164 @@
1-
FROM fedora:30
2-
3-
# Update system and install some build tools
4-
5-
RUN dnf -y update
6-
RUN dnf -y install make automake gcc gcc-c++ kernel-devel git cmake ninja-build python file ncurses-devel flex bison gperf which
7-
8-
# Clone xtensa version of llvm & clang
9-
10-
ARG LLVM_REF=esp-develop
11-
ARG CLANG_REF=esp-develop
12-
13-
RUN git clone -b ${LLVM_REF} https://github.com/espressif/llvm-xtensa.git
14-
RUN git clone -b ${CLANG_REF} https://github.com/espressif/clang-xtensa.git llvm-xtensa/tools/clang
15-
16-
RUN mkdir llvm_build
17-
WORKDIR llvm_build
18-
19-
RUN cmake ../llvm-xtensa -DLLVM_TARGETS_TO_BUILD="Xtensa;X86" -DCMAKE_BUILD_TYPE=Release -G "Ninja"
20-
RUN cmake --build .
21-
22-
WORKDIR /
23-
24-
# Clone esp-idf
25-
26-
RUN git clone -b v3.3-beta3 --recursive https://github.com/espressif/esp-idf.git esp-idf
27-
28-
ENV IDF_PATH=/esp-idf
29-
ENV PATH=$PATH:$IDF_PATH/tools
30-
RUN /usr/bin/python -m pip install --user -r /esp-idf/requirements.txt
31-
32-
# Download xtensa-esp32 toolchain
33-
34-
ARG XTENSA_ESP32_VERSION=1.22.0-80-g6c4433a-5.2.0
35-
RUN curl -o /xtensa-esp32-elf-linux64.tar.gz -L https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-${XTENSA_ESP32_VERSION}.tar.gz && mkdir /esp && cd /esp && tar xzf /xtensa-esp32-elf-linux64.tar.gz && rm /xtensa-esp32-elf-linux64.tar.gz
36-
ENV PATH=$PATH:/esp/xtensa-esp32-elf/bin
37-
38-
RUN echo 'int main() { printf("Hello world\n"); }' > test.c \
39-
&& /llvm_build/bin/clang -target xtensa -fomit-frame-pointer -S test.c -o test.S \
40-
&& xtensa-esp32-elf-as test.S \
41-
&& file a.out \
42-
&& rm a.out test.c test.S
43-
44-
# RUN git clone https://github.com/MabezDev/rust-xtensa.git
45-
ARG RUST_REF=xtensa-target
46-
RUN git clone -b ${RUST_REF} https://github.com/MabezDev/rust-xtensa.git \
47-
&& mkdir /rust_build \
48-
&& cd rust-xtensa \
49-
&& ./configure --llvm-root="/llvm_build" --prefix="/rust_build" \
1+
FROM debian:buster-slim
2+
3+
# -------------------------------------------------------------------
4+
# Toolchain Version Config
5+
# -------------------------------------------------------------------
6+
7+
# Espressif toolchain
8+
ARG ESP_VERSION="1.22.0-80-g6c4433a-5.2.0"
9+
10+
# esp-idf framework
11+
ARG IDF_VERSION="v3.3-beta3"
12+
13+
# llvm-xtensa
14+
ARG CLANG_VERSION="248d9ce8765248d953c3e5ef4022fb350bbe6c51"
15+
ARG LLVM_VERSION="757e18f722dbdcd98b8479e25041b1eee1128ce9"
16+
17+
# rust-xtensa
18+
ARG RUSTC_VERSION="8b4a5a9d98912e97d4d3178705bb2dc19f50d1cb"
19+
20+
# -------------------------------------------------------------------
21+
# Toolchain Path Config
22+
# -------------------------------------------------------------------
23+
24+
ARG TOOLCHAIN="/home/esp32-toolchain"
25+
26+
ARG ESP_BASE="${TOOLCHAIN}/esp"
27+
ENV ESP_PATH "${ESP_BASE}/esp-toolchain"
28+
ENV IDF_PATH "${ESP_BASE}/esp-idf"
29+
30+
ARG LLVM_BASE="${TOOLCHAIN}/llvm"
31+
ARG LLVM_PATH="${LLVM_BASE}/llvm_xtensa"
32+
ARG LLVM_BUILD_PATH="${LLVM_BASE}/llvm_build"
33+
ARG LLVM_INSTALL_PATH="${LLVM_BASE}/llvm_install"
34+
35+
ARG RUSTC_BASE="${TOOLCHAIN}/rustc"
36+
ARG RUSTC_PATH="${RUSTC_BASE}/rust_xtensa"
37+
ARG RUSTC_BUILD_PATH="${RUSTC_BASE}/rust_build"
38+
39+
ENV PATH "/root/.cargo/bin:${ESP_PATH}/bin:${PATH}"
40+
41+
# -------------------------------------------------------------------
42+
# Install expected depdendencies
43+
# -------------------------------------------------------------------
44+
45+
RUN apt-get update \
46+
&& apt-get install -y \
47+
bison \
48+
cmake \
49+
curl \
50+
flex \
51+
g++ \
52+
gcc \
53+
git \
54+
gperf \
55+
libncurses-dev \
56+
make \
57+
ninja-build \
58+
python \
59+
python-pip \
60+
wget \
61+
&& rm -rf /var/lib/apt/lists/*
62+
63+
# -------------------------------------------------------------------
64+
# Setup esp32 toolchain
65+
# -------------------------------------------------------------------
66+
67+
WORKDIR "${ESP_BASE}"
68+
RUN curl \
69+
--proto '=https' \
70+
--tlsv1.2 \
71+
-sSf \
72+
-o "${ESP_PATH}.tar.gz" \
73+
"https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-${ESP_VERSION}.tar.gz" \
74+
&& mkdir "${ESP_PATH}" \
75+
&& tar -xzf "${ESP_PATH}.tar.gz" -C "${ESP_PATH}" --strip-components 1 \
76+
&& rm -rf "${ESP_PATH}.tar.gz"
77+
78+
# -------------------------------------------------------------------
79+
# Setup esp-idf
80+
# -------------------------------------------------------------------
81+
82+
WORKDIR "${ESP_BASE}"
83+
RUN git clone \
84+
--recursive --single-branch -b "${IDF_VERSION}" \
85+
https://github.com/espressif/esp-idf.git \
86+
&& pip install --user -r "${IDF_PATH}/requirements.txt"
87+
88+
# -------------------------------------------------------------------
89+
# Build llvm-xtensa
90+
# -------------------------------------------------------------------
91+
92+
WORKDIR "${LLVM_BASE}"
93+
RUN git clone \
94+
--recursive --single-branch \
95+
https://github.com/espressif/llvm-xtensa.git "${LLVM_PATH}" \
96+
&& git clone \
97+
--recursive --single-branch \
98+
https://github.com/espressif/clang-xtensa.git "${LLVM_PATH}/tools/clang" \
99+
&& cd "${LLVM_PATH}/tools/clang/" \
100+
&& git reset --hard "${CLANG_VERSION}" \
101+
&& cd "${LLVM_PATH}" \
102+
&& git reset --hard "${LLVM_VERSION}" \
103+
&& mkdir -p "${LLVM_BUILD_PATH}" \
104+
&& cd "${LLVM_BUILD_PATH}" \
105+
&& cmake "${LLVM_PATH}" \
106+
-DLLVM_TARGETS_TO_BUILD="Xtensa;X86" \
107+
-DLLVM_INSTALL_UTILS=ON \
108+
-DLLVM_BUILD_TESTS=0 \
109+
-DLLVM_INCLUDE_TESTS=0 \
110+
-DCMAKE_BUILD_TYPE=Release \
111+
-DCMAKE_INSTALL_PREFIX="${LLVM_BASE}/llvm_install" \
112+
-G "Ninja" \
113+
&& ninja install \
114+
&& rm -rf "${LLVM_PATH}" "${LLVM_BUILD_PATH}"
115+
116+
# -------------------------------------------------------------------
117+
# Build rust-xtensa
118+
# -------------------------------------------------------------------
119+
120+
WORKDIR "${RUSTC_BASE}"
121+
RUN git clone \
122+
--recursive --single-branch \
123+
https://github.com/MabezDev/rust-xtensa.git \
124+
"${RUSTC_PATH}" \
125+
&& mkdir -p "${RUSTC_BUILD_PATH}" \
126+
&& cd "${RUSTC_PATH}" \
127+
&& git reset --hard "${RUSTC_VERSION}" \
128+
&& ./configure \
129+
--llvm-root "${LLVM_INSTALL_PATH}" \
130+
--prefix "${RUSTC_BUILD_PATH}" \
50131
&& python ./x.py build \
51-
&& python ./x.py install \
52-
&& cd ..
53-
54-
RUN /rust_build/bin/rustc --print target-list | grep xtensa
55-
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
56-
ENV PATH=$PATH:/root/.cargo/bin
132+
&& python ./x.py install
57133

58-
RUN rustup component add rustfmt
134+
# -------------------------------------------------------------------
135+
# Setup rustup toolchain
136+
# -------------------------------------------------------------------
59137

60-
# install bindgen
61-
RUN cargo install bindgen
62-
# set LIBCLANG_PATH for bindgen
63-
ENV LIBCLANG_PATH=/llvm_build/lib
138+
RUN curl \
139+
--proto '=https' \
140+
--tlsv1.2 \
141+
-sSf \
142+
https://sh.rustup.rs \
143+
| sh -s -- -y --default-toolchain stable \
144+
&& rustup component add rustfmt \
145+
&& rustup toolchain link xtensa "${RUSTC_BUILD_PATH}" \
146+
&& cargo install cargo-xbuild bindgen
64147

65-
RUN rustup toolchain link xtensa /rust_build
66-
RUN rustup run xtensa rustc --print target-list | grep xtensa
148+
# -------------------------------------------------------------------
149+
# Our Project
150+
# -------------------------------------------------------------------
67151

68-
# add xargo
69-
RUN cargo install xargo
70-
ENV XARGO_RUST_SRC=/rust-xtensa/src
152+
ENV PROJECT="/home/project/"
71153

72-
# set up the build directory
73-
RUN mkdir /build
74-
VOLUME /build
75-
WORKDIR /build
154+
ENV XARGO_RUST_SRC="${RUSTC_PATH}/src"
155+
ENV TEMPLATES="${TOOLCHAIN}/templates"
156+
ENV LIBCLANG_PATH="${LLVM_INSTALL_PATH}/lib"
76157

77-
COPY create-project image-project bindgen-project build-project xargo-project /usr/local/bin/
78-
RUN chmod a+x /usr/local/bin/*
79-
COPY templates /templates
158+
VOLUME "${PROJECT}"
159+
WORKDIR "${PROJECT}"
80160

81-
CMD /usr/local/bin/build-project
161+
COPY bindgen-project build-project create-project image-project xbuild-project /usr/local/bin/
162+
COPY templates/ "${TEMPLATES}"
82163

164+
CMD ["/usr/local/bin/build-project"]

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,26 @@ compiler_builtins = { version = "=0.1.16" }
1919

2020
This container image provides a few tools which can be run like this:
2121

22-
docker run -ti -v $PWD:/build:z quay.io/ctron/rust-esp:latest
22+
docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest
2323

2424
### Volume mapping
2525

26-
The `-v $PWD:/build:z` will map the current directory into the location `/build` inside the container.
27-
This is required so that the tools inside the container can work with the project.
26+
The `-v $PWD:/home/project:z` will map the current directory into the location
27+
`/home/project` inside the container. This is required so that the tools inside
28+
the container can work with the project.
2829

2930
The `$PWD` part uses the current directory. This will only work in a Bourne like shell. You can replace
3031
this with the absolute path to your project instead.
3132

3233
You can drop the `:z` suffix, if you don't have SElinux on the host system.
3334

34-
All following example assue that you use `$PWD:/build:z`.
35+
All following example assue that you use `$PWD:/home/project:z`.
3536

3637
### Default command
3738

3839
This will run the default command `build-project`. You can run other commands, e.g. `bash` like this:
3940

40-
docker run -ti -v $PWD:/build:z quay.io/ctron/rust-esp:latest bash
41+
docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest bash
4142

4243
### Labels
4344

@@ -54,12 +55,12 @@ So should the `latest` image break, it should always be possible to switch to a
5455
Initially a few files need to be set up. The ESP-IDF components need to be configured and compiled.
5556
Run the following command to create an initial setup:
5657

57-
docker run -ti -v $PWD:/build:z quay.io/ctron/rust-esp:latest create-project
58+
docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest create-project
5859

5960
This will create (overwrite) as few files which are required to build the project.
6061
Next run:
6162

62-
docker run -ti -v $PWD:/build:z quay.io/ctron/rust-esp:latest make menuconfig
63+
docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest make menuconfig
6364

6465
Which will start the ESP-IDF build and shows you the menu config tool for configuring
6566
your ESP project. Be sure to save when you exit.
@@ -68,15 +69,19 @@ your ESP project. Be sure to save when you exit.
6869

6970
In order to build the project, run the following command:
7071

71-
docker run -ti -v $PWD:/build:z quay.io/ctron/rust-esp:latest
72+
docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest
7273

7374
This will compile the ESP-IDF part, the rust part and finally convert it to an image
7475
which you can upload to your ESP.
7576

7677
## Uploading
7778

78-
You can then upload the image using an `esptool` on any machnine. As it might be difficult to do this
79-
from inside the container, it is recommended to do this on the host system:
79+
You can then upload the image using the `flash-project` executable:
80+
81+
docker run -ti --device=/dev/ttyUSB0 -v $PWD:/home/project:z rust-esp32:latest flash-project
82+
83+
If this doesn't work or you need to use differnt tool it might be easier to
84+
upload the image via `esptool` from the host machine. To do this call:
8085

8186
esptool write_flash 0x10000 esp-app.bin
8287

@@ -94,7 +99,7 @@ You can also build the container image yourself, by cloning this repository and
9499
* A test on Windows shows that, yes it works. But with some quirks:
95100
* The menu `make menuconfig` renders a bit weird. Maybe the new Windows terminal will fix this.
96101
* The first `make app` will run just fine, but after that it fails to compile. Maybe some
97-
issue with the Windows CIFS mapping in Docker. However, you can skip this step and run `xargo-project`
102+
issue with the Windows CIFS mapping in Docker. However, you can skip this step and run `xbuild-project`
98103
instead. That will only compile the rust part.
99104
* In theory this should work also with with the ESP8266. A few tweaks for the build files
100105
will be required, and I didn't test this.

bindgen-project

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
#!/usr/bin/env bash
22

3-
set -ex
3+
set -e
44

55
FLAGS=""
6-
FLAGS+=" --sysroot=/esp/xtensa-esp32-elf/xtensa-esp32-elf/sysroot"
7-
FLAGS+=" -I/build/build/include"
6+
FLAGS+=" --sysroot=${ESP_PATH}/xtensa-esp32-elf/sysroot"
7+
FLAGS+=" -I${PROJECT}/build/include"
88
FLAGS+=" -D__bindgen"
99
FLAGS+=" -target xtensa"
1010
FLAGS+=" -x c"
1111

12-
for i in $(find "$IDF_PATH/components" -maxdepth 3 -name include); do
13-
FLAGS+=" -I$i"
14-
done
12+
while read -r include; do
13+
FLAGS+=" -I${include}"
14+
done <<< "$(find "${IDF_PATH}/components" -maxdepth 3 -name include)"
1515

16-
: ${BINDGEN_FLAGS:="--use-core --no-layout-tests"}
16+
: "${BINDGEN_FLAGS:=--use-core --no-layout-tests}"
1717

18+
#shellcheck disable=SC2086
1819
bindgen $BINDGEN_FLAGS --output esp32-sys/src/bindings.rs esp32-sys/src/bindings.h -- $FLAGS
19-

build-project

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -e
44

55
die() { echo "$*" 1>&2 ; exit 1 ; }
66

7-
test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /build to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/build:z rust-esp"
7+
test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /home/build to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/build:z rust-esp"
88

99
for i in esp-idf .cargo main; do
1010
test -d "$i" || die "'$i' is missing. Use 'create-project' to set up the build."
@@ -24,7 +24,7 @@ if test -d esp32-sys; then
2424
fi
2525
fi
2626

27-
xargo-project
27+
xbuild-project
2828
image-project
2929

3030
echo Build complete

create-project

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ set -e
44

55
die() { echo "$*" 1>&2 ; exit 1 ; }
66

7-
test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /build to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/build:z rust-esp"
7+
test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /build to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/home/project/build:z rust-esp"
88

99
echo "Creating Makefile (Makefile)"
10-
cp /templates/Makefile Makefile
10+
cp "${TEMPLATES}/Makefile" Makefile
1111

1212
echo "Creating esp-idf symlink (esp-idf -> /esp-idf)"
13-
ln -sf /esp-idf esp-idf
13+
ln -sf "${IDF_PATH}" esp-idf
1414

1515
echo "Creating cargo config (.cargo/config)"
1616
mkdir -p .cargo
17-
cp /templates/cargo.config .cargo/config
17+
cp "${TEMPLATES}/cargo.config" .cargo/config
1818

1919
echo "Creating main application wrapper (main/esp_app_main.c)"
2020
mkdir -p main
21-
cp /templates/main.c main/esp_app_main.c
22-
cp /templates/component.mk main/
21+
cp "${TEMPLATES}/main.c" main/esp_app_main.c
22+
cp "${TEMPLATES}/component.mk" main/
2323

0 commit comments

Comments
 (0)