Corriendo Rust en ARM32v7 via QEMU
Introducción
En este artículo, vamos a explorar cómo usar QEMU para emular la arquitectura ARM32v7 y compilar y ejecutar código en Rust como si fuese nativo para la arquitectura ARM32v7.
Existen algunas desventajas y consideraciones de rendimiento al usar este enfoque; puede ser más simple pero mucho más lento para proyectos grandes.
El código fuente de este artículo está aquí y la imagen de Docker está aquí.
Este artículo puede considerarse una parte 2 de Running Rust on ARM32v7K3S Oracle Cluster, por lo que no vamos a crear el proyecto de Rust desde cero aquí, sino que nos enfocaremos en compilar y ejecutar el proyecto.
Requisitos previos
Vamos directo al ejemplo
El nuevo Dockerfile
Vas a notar que este Dockerfile es mucho más simple que los de artículos anteriores, ya que se ejecuta de manera nativa como ARM32v7. La principal diferencia es que usa la imagen base arm32v7/rust:1.63.0
, y este enfoque puede ser extendido para más arquitecturas. Consultá este artículo para más información.
## builder
FROM arm32v7/rust:1.63.0 as builder
RUN apt update && apt upgrade -y
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release
## release
FROM arm32v7/rust:1.63
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/target/release/rcv /usr/src/app
COPY --from=builder /usr/src/app/cv.md /usr/src/app
CMD ["/usr/src/app/rcv"]
Últimos pasos para QEMU/Docker
Después de instalar los paquetes necesarios, todavía necesitarás realizar algunos pasos simples para que funcione con Docker y Buildah. El primer comando es necesario para que Docker pueda utilizar la emulación de QEMU requerida, y el segundo es solo para validar que todo esté funcionando correctamente:
# Habilitar la emulación QEMU en Docker
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# Validar que todo esté funcionando correctamente
docker run --rm -t arm32v7/ubuntu uname -m
Si ves que el sistema te devuelve algo como armv7l
, entonces todo está configurado correctamente para emular la arquitectura ARM32v7 usando Docker.
❯ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
Setting /usr/bin/qemu-armeb-static as binfmt interpreter for armeb
Setting /usr/bin/qemu-sparc-static as binfmt interpreter for sparc
Setting /usr/bin/qemu-sparc32plus-static as binfmt interpreter for sparc32plus
Setting /usr/bin/qemu-sparc64-static as binfmt interpreter for sparc64
Setting /usr/bin/qemu-ppc-static as binfmt interpreter for ppc
Setting /usr/bin/qemu-ppc64-static as binfmt interpreter for ppc64
Setting /usr/bin/qemu-ppc64le-static as binfmt interpreter for ppc64le
Setting /usr/bin/qemu-m68k-static as binfmt interpreter for m68k
Setting /usr/bin/qemu-mips-static as binfmt interpreter for mips
Setting /usr/bin/qemu-mipsel-static as binfmt interpreter for mipsel
Setting /usr/bin/qemu-mipsn32-static as binfmt interpreter for mipsn32
Setting /usr/bin/qemu-mipsn32el-static as binfmt interpreter for mipsn32el
Setting /usr/bin/qemu-mips64-static as binfmt interpreter for mips64
Setting /usr/bin/qemu-mips64el-static as binfmt interpreter for mips64el
Setting /usr/bin/qemu-sh4-static as binfmt interpreter for sh4
Setting /usr/bin/qemu-sh4eb-static as binfmt interpreter for sh4eb
Setting /usr/bin/qemu-s390x-static as binfmt interpreter for s390x
Setting /usr/bin/qemu-aarch64-static as binfmt interpreter for aarch64
Setting /usr/bin/qemu-aarch64_be-static as binfmt interpreter for aarch64_be
Setting /usr/bin/qemu-hppa-static as binfmt interpreter for hppa
Setting /usr/bin/qemu-riscv32-static as binfmt interpreter for riscv32
Setting /usr/bin/qemu-riscv64-static as binfmt interpreter for riscv64
Setting /usr/bin/qemu-xtensa-static as binfmt interpreter for xtensa
Setting /usr/bin/qemu-xtensaeb-static as binfmt interpreter for xtensaeb
Setting /usr/bin/qemu-microblaze-static as binfmt interpreter for microblaze
Setting /usr/bin/qemu-microblazeel-static as binfmt interpreter for microblazeel
Setting /usr/bin/qemu-or1k-static as binfmt interpreter for or1k
Setting /usr/bin/qemu-hexagon-static as binfmt interpreter for hexagon
❯ docker run --rm -t arm32v7/ubuntu uname -m
Unable to find image 'arm32v7/ubuntu:latest' locally
latest: Pulling from arm32v7/ubuntu
af25ea170fdc: Pull complete
Digest: sha256:7723f8c211cbc089f836e13136b35157ba572b61e0419d8f978917fca049db68
Status: Downloaded newer image for arm32v7/ubuntu:latest
WARNING: The requested image's platform (linux/arm/v7) does not match the detected host platform (linux/amd64) and no specific platform was requested
armv7l
Error de nombres cortos
Si recibes un error sobre nombres cortos al intentar descargar imágenes, agrega la siguiente línea a tu archivo /etc/containers/registries.conf
:
unqualified-search-registries = ["docker.io"]
Vamos a construirlo
Para la compilación utilizaremos Buildah, ya que es más inteligente que Docker para este tipo de escenarios.
❯ buildah build -f Dockerfile.armv7v2 .
[1/2] STEP 1/5: FROM arm32v7/rust:1.63.0 AS builder
WARNING: image platform ({arm linux [] v7}) does not match the expected platform ({amd64 linux [] })
[1/2] STEP 2/5: RUN apt update && apt upgrade -y
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:2 http://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:3 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:4 http://deb.debian.org/debian bullseye/main armhf Packages [7949 kB]
Get:5 http://deb.debian.org/debian-security bullseye-security/main armhf Packages [175 kB]
Get:6 http://deb.debian.org/debian bullseye-updates/main armhf Packages [2608 B]
Fetched 8334 kB in 1min 11s (117 kB/s)
Reading package lists...
Building dependency tree...
Reading state information...
4 packages can be upgraded. Run 'apt list --upgradable' to see them.
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
The following packages will be upgraded:
libxslt1-dev libxslt1.1 zlib1g zlib1g-dev
4 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 819 kB of archives.
After this operation, 6144 B of additional disk space will be used.
Get:1 http://deb.debian.org/debian-security bullseye-security/main armhf zlib1g-dev armhf 1:1.2.11.dfsg-2+deb11u2 [185 kB]
Get:2 http://deb.debian.org/debian-security bullseye-security/main armhf zlib1g armhf 1:1.2.11.dfsg-2+deb11u2 [85.0 kB]
Get:3 http://deb.debian.org/debian-security bullseye-security/main armhf libxslt1-dev armhf 1.1.34-4+deb11u1 [329 kB]
Get:4 http://deb.debian.org/debian-security bullseye-security/main armhf libxslt1.1 armhf 1.1.34-4+deb11u1 [221 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 819 kB in 5s (167 kB/s)
(Reading database ... 22525 files and directories currently installed.)
Preparing to unpack .../zlib1g-dev_1%3a1.2.11.dfsg-2+deb11u2_armhf.deb ...
Unpacking zlib1g-dev:armhf (1:1.2.11.dfsg-2+deb11u2) over (1:1.2.11.dfsg-2+deb11u1) ...
Preparing to unpack .../zlib1g_1%3a1.2.11.dfsg-2+deb11u2_armhf.deb ...
Unpacking zlib1g:armhf (1:1.2.11.dfsg-2+deb11u2) over (1:1.2.11.dfsg-2+deb11u1) ...
Setting up zlib1g:armhf (1:1.2.11.dfsg-2+deb11u2) ...
(Reading database ... 22525 files and directories currently installed.)
Preparing to unpack .../libxslt1-dev_1.1.34-4+deb11u1_armhf.deb ...
Unpacking libxslt1-dev:armhf (1.1.34-4+deb11u1) over (1.1.34-4) ...
Preparing to unpack .../libxslt1.1_1.1.34-4+deb11u1_armhf.deb ...
Unpacking libxslt1.1:armhf (1.1.34-4+deb11u1) over (1.1.34-4) ...
Setting up zlib1g-dev:armhf (1:1.2.11.dfsg-2+deb11u2) ...
Setting up libxslt1.1:armhf (1.1.34-4+deb11u1) ...
Setting up libxslt1-dev:armhf (1.1.34-4+deb11u1) ...
Processing triggers for libc-bin (2.31-13+deb11u3) ...
[1/2] STEP 3/5: WORKDIR /usr/src/app
[1/2] STEP 4/5: COPY . .
[1/2] STEP 5/5: RUN cargo build --release
Updating crates.io index
Downloading crates ...
Downloaded aho-corasick v0.7.18
Downloaded fnv v1.0.7
Downloaded pin-project-lite v0.2.9
Downloaded block-buffer v0.10.2
Downloaded adler v1.0.2
Downloaded markdown v0.3.0
Downloaded actix-rt v2.7.0
Downloaded actix-codec v0.5.0
Downloaded lazy_static v1.4.0
Downloaded futures-task v0.3.23
Downloaded signal-hook-registry v1.4.0
Downloaded pin-utils v0.1.0
Downloaded actix-web v4.1.0
Downloaded once_cell v1.13.1
Downloaded semver v1.0.13
Downloaded crc32fast v1.3.2
Downloaded language-tags v0.3.2
Downloaded getrandom v0.2.7
Downloaded miniz_oxide v0.5.3
Downloaded bytes v1.2.1
Downloaded generic-array v0.14.6
Downloaded rand_chacha v0.3.1
Downloaded cfg-if v1.0.0
Downloaded tokio v1.20.1
Downloaded futures-util v0.3.23
Downloaded flate2 v1.0.24
Downloaded jobserver v0.1.24
Downloaded time-macros v0.2.4
Downloaded matches v0.1.9
Downloaded sha1 v0.10.1
Downloaded form_urlencoded v1.0.1
Downloaded indexmap v1.9.1
Downloaded base64 v0.13.0
Downloaded local-waker v0.1.3
Downloaded rand v0.8.5
Downloaded parking_lot_core v0.9.3
Downloaded actix-utils v3.0.0
Downloaded crypto-common v0.1.6
Downloaded firestorm v0.5.1
Downloaded actix-http v3.2.1
Downloaded local-channel v0.1.3
Downloaded mime v0.3.16
Downloaded parking_lot v0.12.1
Downloaded futures-sink v0.3.23
Downloaded derive_more v0.99.17
Downloaded cc v1.0.73
Downloaded bitflags v1.3.2
Downloaded paste v1.0.8
Downloaded brotli-decompressor v2.3.2
Downloaded tinyvec_macros v0.1.0
Downloaded h2 v0.3.14
Downloaded log v0.4.17
Downloaded tinyvec v1.6.0
Downloaded ryu v1.0.11
Downloaded tokio-util v0.7.3
Downloaded actix-web-codegen v4.0.1
Downloaded syn v1.0.99
Downloaded cookie v0.16.0
Downloaded itoa v1.0.3
Downloaded pipeline v0.5.0
Downloaded serde_urlencoded v0.7.1
Downloaded num_threads v0.1.6
Downloaded socket2 v0.4.6
Downloaded scopeguard v1.1.0
Downloaded percent-encoding v2.1.0
Downloaded ppv-lite86 v0.2.16
Downloaded mio v0.8.4
Downloaded serde v1.0.144
Downloaded num_cpus v1.13.1
Downloaded quote v1.0.21
Downloaded digest v0.10.3
Downloaded bytestring v1.1.0
Downloaded alloc-no-stdlib v2.0.3
Downloaded proc-macro2 v1.0.43
Downloaded http v0.2.8
Downloaded tracing-core v0.1.29
Downloaded unicode-normalization v0.1.21
Downloaded zstd-safe v5.0.2+zstd.1.5.2
Downloaded smallvec v1.9.0
Downloaded httpdate v1.0.2
Downloaded unicode-bidi v0.3.8
Downloaded regex-syntax v0.6.27
Downloaded regex v1.6.0
Downloaded actix-router v0.5.0
Downloaded version_check v0.9.4
Downloaded ahash v0.7.6
Downloaded memchr v2.5.0
Downloaded url v2.2.2
Downloaded tracing v0.1.36
Downloaded autocfg v1.1.0
Downloaded actix-server v2.1.1
Downloaded zstd v0.11.2+zstd.1.5.2
Downloaded slab v0.4.7
Downloaded rand_core v0.6.3
Downloaded actix-service v2.0.2
Downloaded rustc_version v0.4.0
Downloaded actix-macros v0.2.3
Downloaded httparse v1.7.1
Downloaded serde_json v1.0.85
Downloaded lock_api v0.4.8
Downloaded hashbrown v0.12.3
Downloaded typenum v1.15.0
Downloaded convert_case v0.4.0
Downloaded unicode-ident v1.0.3
Downloaded futures-core v0.3.23
Downloaded alloc-stdlib v0.2.1
Downloaded time v0.3.14
Downloaded idna v0.2.3
Downloaded libc v0.2.132
Downloaded zstd-sys v2.0.1+zstd.1.5.2
Downloaded brotli v3.3.4
Downloaded encoding_rs v0.8.31
Compiling libc v0.2.132
Compiling cfg-if v1.0.0
Compiling memchr v2.5.0
Compiling autocfg v1.1.0
Compiling log v0.4.17
Compiling version_check v0.9.4
Compiling pin-project-lite v0.2.9
Compiling futures-core v0.3.23
Compiling bytes v1.2.1
Compiling once_cell v1.13.1
Compiling parking_lot_core v0.9.3
Compiling serde v1.0.144
Compiling smallvec v1.9.0
Compiling scopeguard v1.1.0
Compiling proc-macro2 v1.0.43
Compiling typenum v1.15.0
Compiling itoa v1.0.3
Compiling futures-task v0.3.23
Compiling unicode-ident v1.0.3
Compiling quote v1.0.21
Compiling futures-util v0.3.23
Compiling syn v1.0.99
Compiling percent-encoding v2.1.0
Compiling pin-utils v0.1.0
Compiling futures-sink v0.3.23
Compiling zstd-safe v5.0.2+zstd.1.5.2
Compiling local-waker v0.1.3
Compiling crc32fast v1.3.2
Compiling tinyvec_macros v0.1.0
Compiling fnv v1.0.7
Compiling matches v0.1.9
Compiling alloc-no-stdlib v2.0.3
Compiling regex-syntax v0.6.27
Compiling encoding_rs v0.8.31
Compiling adler v1.0.2
Compiling httparse v1.7.1
Compiling ppv-lite86 v0.2.16
Compiling paste v1.0.8
Compiling hashbrown v0.12.3
Compiling num_threads v0.1.6
Compiling bitflags v1.3.2
Compiling ryu v1.0.11
Compiling convert_case v0.4.0
Compiling unicode-bidi v0.3.8
Compiling firestorm v0.5.1
Compiling serde_json v1.0.85
Compiling time-macros v0.2.4
Compiling language-tags v0.3.2
Compiling httpdate v1.0.2
Compiling base64 v0.13.0
Compiling mime v0.3.16
Compiling lazy_static v1.4.0
Compiling pipeline v0.5.0
Compiling tinyvec v1.6.0
Compiling actix-utils v3.0.0
Compiling form_urlencoded v1.0.1
Compiling tracing-core v0.1.29
Compiling alloc-stdlib v0.2.1
Compiling miniz_oxide v0.5.3
Compiling http v0.2.8
Compiling bytestring v1.1.0
Compiling generic-array v0.14.6
Compiling ahash v0.7.6
Compiling cookie v0.16.0
Compiling lock_api v0.4.8
Compiling tokio v1.20.1
Compiling slab v0.4.7
Compiling indexmap v1.9.1
Compiling brotli-decompressor v2.3.2
Compiling tracing v0.1.36
Compiling flate2 v1.0.24
Compiling aho-corasick v0.7.18
Compiling actix-service v2.0.2
Compiling unicode-normalization v0.1.21
Compiling jobserver v0.1.24
Compiling mio v0.8.4
Compiling socket2 v0.4.6
Compiling signal-hook-registry v1.4.0
Compiling getrandom v0.2.7
Compiling num_cpus v1.13.1
Compiling time v0.3.14
Compiling cc v1.0.73
Compiling idna v0.2.3
Compiling parking_lot v0.12.1
Compiling rand_core v0.6.3
Compiling brotli v3.3.4
Compiling regex v1.6.0
Compiling rand_chacha v0.3.1
Compiling url v2.2.2
Compiling rand v0.8.5
Compiling crypto-common v0.1.6
Compiling block-buffer v0.10.2
Compiling digest v0.10.3
Compiling local-channel v0.1.3
Compiling zstd-sys v2.0.1+zstd.1.5.2
Compiling markdown v0.3.0
Compiling sha1 v0.10.1
Compiling serde_urlencoded v0.7.1
Compiling actix-router v0.5.0
Compiling tokio-util v0.7.3
Compiling actix-rt v2.7.0
Compiling actix-server v2.1.1
Compiling actix-codec v0.5.0
Compiling h2 v0.3.14
Compiling derive_more v0.99.17
Compiling actix-macros v0.2.3
Compiling actix-web-codegen v4.0.1
Compiling zstd v0.11.2+zstd.1.5.2
Compiling actix-http v3.2.1
Compiling actix-web v4.1.0
Compiling rcv v0.1.0 (/usr/src/app)
Finished release [optimized] target(s) in 6m 41s
[2/2] STEP 1/5: FROM arm32v7/rust:1.63
Resolving "arm32v7/rust" using unqualified-search registries (/etc/containers/registries.conf)
Trying to pull docker.io/arm32v7/rust:1.63...
Getting image source signatures
Copying blob 60ad8c571b2b skipped: already exists
Copying blob 94cbc350f4a2 skipped: already exists
Copying blob c715a126a4d5 skipped: already exists
Copying blob cdfc7e160811 skipped: already exists
Copying blob 3cecc62e2752 skipped: already exists
Copying blob 818eb872fe75 skipped: already exists
Copying config d0646b193e done
Writing manifest to image destination
Storing signatures
WARNING: image platform ({arm linux [] v7}) does not match the expected platform ({amd64 linux [] })
[2/2] STEP 2/5: WORKDIR /usr/src/app
[2/2] STEP 3/5: COPY --from=builder /usr/src/app/target/release/rcv /usr/src/app
[2/2] STEP 4/5: COPY --from=builder /usr/src/app/cv.md /usr/src/app
[2/2] STEP 5/5: CMD ["/usr/src/app/rcv"]
[2/2] COMMIT
Getting image source signatures
Copying blob b74e98d1b921 skipped: already exists
Copying blob 6c3d1ef471ee skipped: already exists
Copying blob 403a5f26ee02 skipped: already exists
Copying blob d55191df9034 skipped: already exists
Copying blob 1f4f3f20d97e skipped: already exists
Copying blob 54a3ca211559 skipped: already exists
Copying blob 7fd29dd92a8e done
Copying config f9fe5e59b8 done
Writing manifest to image destination
Storing signatures
--> f9fe5e59b8d
f9fe5e59b8d124fe147ef045ceb9195421a2613e48df91f48875ed11c1d9f5de
Probando
Una vez la imagen esta lista la podemos copiar al docker daemon para poder usarla
❯ buildah push f9fe5e59b8d docker-daemon:rcv:f9fe5e59b8d
Getting image source signatures
Copying blob b74e98d1b921 done
Copying blob 6c3d1ef471ee done
Copying blob 403a5f26ee02 done
Copying blob d55191df9034 done
Copying blob 1f4f3f20d97e done
Copying blob 54a3ca211559 done
Copying blob 7fd29dd92a8e done
Copying config f9fe5e59b8 done
Writing manifest to image destination
Storing signatures
❯ docker run -p 8080:8080 f9fe5e59b8d
WARNING: The requested image's platform (linux/arm/v7) does not match the detected host platform (linux/amd64) and no specific platform was requested
[1662239178][172.17.0.1]: Processing cv request...
NOTA: la advertencia de la plataforma es por que estamos emulando con QEMU, nada de que preocuparse.
Consideraciones de rendimiento
Este proyecto, construido con la cadena de herramientas de Rust y luego copiado a una imagen ARM32v7, tomó 2 minutos. Sin embargo, utilizando QEMU y la emulación proporcionada, tomó alrededor de 8 minutos y medio. Es importante tener en cuenta esta diferencia, ya que el tiempo es considerablemente mayor.
Extra
Puedes verlo funcionando aquí, es un currículum vitae en HTML muy básico.
Para más detalles y para ver cómo encajan todas las piezas, te animo a clonar el repositorio, probarlo y modificarlo para crear tu propia versión.
Notas finales
No olvides revisar los enlaces si quieres aprender más sobre los ejemplos. ¡Espero que te haya gustado! Nos vemos en twitter o github.
El código fuente de este artículo está disponible aquí.
Errata
Si encuentras algún error o tienes alguna sugerencia, por favor mándame un mensaje para corregirlo.
No tienes cuenta? Regístrate aqui
Ya registrado? Iniciar sesión a tu cuenta ahora.
-
Comentarios
Online: 0
Por favor inicie sesión para poder escribir comentarios.