Flutter Community
Published in

Flutter Community

Running Dart on Arm Servers

By Chris Swan, engineer at Atsign

Last week I wrote about easier automation using GitHub Actions to build multi-architecture Docker images. That led me to another question — how to create the binaries to go into those builds? If I’m making an Arm image, then I need an Arm binary to go into that image.

At the moment dart compile only compiles self-contained executable files for the architecture it’s being run on. This is a shame, as the underlying tooling is perfectly capable of doing cross-compilation as J-P Nurmi explains in Cross-compiling Dart apps.

Without cross-compilation the only alternative is to run dart compile from the Dart SDK on each of the target platforms. Google handily packages up the SDK into a Docker image google/dart but unfortunately, that's only available for x86_64 (aka amd64). The Dockerfile for that image also makes use of the SDK apt package, but that too is only available for x86_64.

So to run dart compile on multiple architectures, I first needed a multi-arch build image:

FROM debian:stableARG DART_VERSION="2.12.4"WORKDIR /tmp/RUN \
apt-get -q update && apt-get install --no-install-recommends -y -q \
gnupg2 curl git ca-certificates unzip openssh-client && \
case "$(uname -m)" in armv7l | armv7) ARCH="arm";; aarch64) ARCH="arm64";; *) ARCH="x64";; esac && \
curl -O https://storage.googleapis.com/dart-archive/channels/stable/release/$DART_VERSION/sdk/dartsdk-linux-$ARCH-release.zip && \
unzip dartsdk-linux-$ARCH-release.zip -d /usr/lib/ && \
rm dartsdk-linux-$ARCH-release.zip && \
mv /usr/lib/dart-sdk /usr/lib/dart
ENV DART_SDK /usr/lib/dart
ENV PATH $DART_SDK/bin:/root/.pub-cache/bin:$PATH

This is installing some key dependencies (the same as google/dart) and then downloading and installing the Dart SDK according to the output from uname -m to establish the underlying architecture.

With the build image it’s then possible to create a lightweight run image based on the work by Google engineer Tony Pujals with his subfuzion/dart-docker-slim:

# Originally based on subfuzion/dart-docker-slim
# Using our buildimage as it supports x64|arm|arm64
FROM atsigncompany/buildimage AS dart
# Do all the copying to an output dir here first
# as the buildimage has a shell that can be used
# for multi-arch conditionals
mkdir -p /output/lib && mkdir -p /output/etc && \
mkdir -p /output/etc/ssl/certs && \
mkdir -p /output/usr/share/ca-certificates && \
case "$(uname -m)" in \
armv7l | armv7) ARCH="arm-linux-gnueabihf" ; \
mkdir -p /output/lib/$ARCH ; \
cp /lib/ld-linux-armhf.so.3 /output/lib/ld-linux-armhf.so.3 ; \
cp /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 \
/output/lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 ;; \
aarch64) ARCH="aarch64-linux-gnu" ; \
mkdir -p /output/lib/$ARCH ; \
cp /lib/ld-linux-aarch64.so.1 /output/lib/ld-linux-aarch64.so.1 ; \
cp /lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 \
/output/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 ;; \
*) ARCH="x86_64-linux-gnu" ; \
mkdir -p /output/lib/$ARCH ; mkdir -p /output/lib64/ ; \
cp /lib64/ld-linux-x86-64.so.2 /output/lib64/ld-linux-x86-64.so.2 ;; \
esac && \
cp /lib/$ARCH/libdl.so.2 /output/lib/$ARCH/libdl.so.2 && \
cp /lib/$ARCH/libc.so.6 /output/lib/$ARCH/libc.so.6 && \
cp /lib/$ARCH/libm.so.6 /output/lib/$ARCH/libm.so.6 && \
cp /lib/$ARCH/librt.so.1 /output/lib/$ARCH/librt.so.1 && \
cp /lib/$ARCH/libpthread.so.0 /output/lib/$ARCH/libpthread.so.0 && \
cp /lib/$ARCH/libnss_dns.so.2 /output/lib/$ARCH/libnss_dns.so.2 && \
cp /lib/$ARCH/libresolv.so.2 /output/lib/$ARCH/libresolv.so.2 && \
cp /etc/nsswitch.conf /output/etc/nsswitch.conf && \
cp /etc/resolv.conf /output/etc/resolv.conf && \
cp -R /usr/share/ca-certificates /output/usr/share/ca-certificates && \
cp -R /etc/ssl/certs /output/etc/ssl/certs
FROM scratch
COPY --from=dart /output /
# Is this even really needed, as Docker uses host hosts?
COPY ./at-runimage/etc-hosts /etc/hosts

Once again this is using the output of uname -m to determine the correct dependencies to copy in from the build image.

The build image and run image can then be brought together with a Dart application. I put together a trivial one dartshowplatform that prints out version and platform information like:

$ sudo docker run -it  atsigncompany/dartshowplatform
2.12.4 (stable) (Thu Apr 15 12:26:53 2021 +0200) on "linux_arm64"

Here’s the Dockerfile:

FROM atsigncompany/buildimage
COPY ./dartshowplatform/showplatform.dart .
RUN dart compile exe /app/showplatform.dart -o /app/dartshowplatform
FROM atsigncompany/runimage
COPY --from=0 /app/dartshowplatform /app/dartshowplatform
ENTRYPOINT ["/app/dartshowplatform"]

The build image is used to run dart compile and then the binary created from that is copied into the run image.

The full source etc. for the stuff above is available on GitHub atsign-company/at_dockerfiles.

If you’re wondering why we’re doing this, it’s because people are asking us to support Arm and Arm64, as there’s huge growth in the Arm footprint as illustrated above. We can expect it won’t be long before we’re having to add RISC-V support too, as that Instruction Set Architecture (ISA) gains traction and wider adoption. The days of WinTel hegemony are over, which means dealing with a lot more heterogeneity, and that demands greater automation to avoid being drowned by the complexity of it all.

Atsign is a tech startup committed to transforming how the modern Internet treats people’s data. To learn more about Atsign and their mission, check out their website.

Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm




Articles and Stories from the Flutter Community

Recommended from Medium

How Kubernetes is used in industries and how does industries get benefited using Kubernetes…?

AWS Data Transfer

[Notes] Spring Boot

Using scikit-learn model into Java app

Comparing Mean Absolute Error for the same model in Python and in Java

Generate PDF documents in .NET using PDFsharp

CS371P Spring 2020: Final Entry

Recon for Bug Bounty : Using Google Cloud Shell

From Terrafrom to CDK — Former2

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store


Now for some Internet Optimism

More from Medium

How to build your own Flutter slide puzzle

How To Add Custom Icons To Your Flutter Application

Simplify Flutter & AngularDart development with common code

Send push notifications from a Flutter app to devices with Firebase