From 7d64d29ac7af460ffd7a98f5bbe48f165218b0bd Mon Sep 17 00:00:00 2001 From: Leonid Evdokimov Date: Sat, 1 Feb 2020 23:28:22 +0300 Subject: [PATCH] Fix build for Raspberry Pi 1 B+ and Zero --- .dockerignore | 1 + .gitignore | 4 +- ...erfile.ubxtool => Dockerfile.ubxtool.glibc | 1 + Dockerfile.ubxtool.static | 33 +++++++ Makefile | 3 + bin/.keep | 0 build-ubxtool | 86 +++++++++++++++---- ubxtool.cc | 1 + 8 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 .dockerignore rename Dockerfile.ubxtool => Dockerfile.ubxtool.glibc (98%) create mode 100644 Dockerfile.ubxtool.static create mode 100644 bin/.keep diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5cd7ec7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +/bin/ubxtool.* diff --git a/.gitignore b/.gitignore index 3b952bb..e5885c3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,9 @@ testrunner tlecatch ubxtool ubxtool.nodeps -ubxtool.nodeps.* +ubxtool.static +# - created by build-ubxtool +/bin/ubxtool.* # - created by update-tles active.txt beidou.txt diff --git a/Dockerfile.ubxtool b/Dockerfile.ubxtool.glibc similarity index 98% rename from Dockerfile.ubxtool rename to Dockerfile.ubxtool.glibc index 645ce12..053c26d 100644 --- a/Dockerfile.ubxtool +++ b/Dockerfile.ubxtool.glibc @@ -14,6 +14,7 @@ RUN set -ex && \ apt-get install -y \ build-essential \ g++ \ + git \ libprotobuf-dev \ make \ protobuf-compiler \ diff --git a/Dockerfile.ubxtool.static b/Dockerfile.ubxtool.static new file mode 100644 index 0000000..eb140d4 --- /dev/null +++ b/Dockerfile.ubxtool.static @@ -0,0 +1,33 @@ +# See `build-ubxtool` script for cross-compilation options. + +# 1. GCC has issues with exception unwinding with static build of libmusl. +# The bug is fixed for gcc-10, but alpine:3.11 has 9.2.0-r3 and alpine:3.10 has 8.3.0-r0. +# Both are affected per test and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91737 +# +# 2. clang-9.0.0-r1 from alpine:3.11 generates wrong FPU instructions for Raspberry Pi 1 B+ and Zero. +# It uses d{16..31} registers for a VFPv2 FPU and that leads to SIGILL. +# The bug is described at https://reviews.llvm.org/D67375 +# The bug is fixed in clang-10: https://reviews.llvm.org/rGddf5e86c222c6b5226be53e1250421fe608bb4d0 +# +# 3. clang-8.0.0-r0 from alpine:3.10 is not affected by the bug, so we use it. +FROM alpine:3.10 AS build-env + +# g++ is still installed to bring C++ headers like , , etc. +# See https://pkgs.alpinelinux.org/contents?file=iostream&branch=v3.10&arch=armhf +RUN set -ex && \ + apk add --no-cache \ + clang \ + g++ \ + git \ + make \ + protobuf-dev \ + && \ + : + +ADD . /galmon/ +WORKDIR /galmon/ +RUN CXX=clang make ubxtool.static + +FROM scratch +COPY --from=build-env /galmon/ubxtool.static /opt/ubxtool +ENTRYPOINT ["/opt/ubxtool"] diff --git a/Makefile b/Makefile index 04a2b1a..bd22101 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,9 @@ UBXTOOL_DEPS = navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-5.2.1/src/format.o gal ubxtool: $(UBXTOOL_DEPS) $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread +# Static build with musl on alpine and clang +ubxtool.static: $(UBXTOOL_DEPS) + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread -lstdc++ -static # Static linking of `glibc` is non-trivial, so glibc is kept dynamically linked ubxtool.nodeps: $(UBXTOOL_DEPS) $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib /usr/lib/*-linux-*/libprotobuf.a -pthread -static-libgcc -static-libstdc++ diff --git a/bin/.keep b/bin/.keep new file mode 100644 index 0000000..e69de29 diff --git a/build-ubxtool b/build-ubxtool index 5f4ae80..8afebca 100755 --- a/build-ubxtool +++ b/build-ubxtool @@ -3,31 +3,87 @@ # The script relies on the following project: # - https://github.com/multiarch/qemu-user-static # - https://github.com/multiarch/ubuntu-core +# - https://github.com/multiarch/alpine # -# Another easy cross-compilation option is to use https://github.com/docker/binfmt +# It's also probably possible to use more official {i386,amd64,arm32v6,arm32v7,arm64v8}/alpine +# images adding qemu binary from multiarch/qemu-user-static:{arm,arm64} to them. # # Register qemu-user-static before building # $ docker run --rm --privileged multiarch/qemu-user-static:register --reset set -e -arch=${1:-native} - -case "$arch" in - native) - tag=latest - from=ubuntu:bionic - ;; - x86|x86_64|arm64|armhf) - tag=${arch} - from=multiarch/ubuntu-core:${arch}-bionic - ;; +this_mach=$(uname --machine) + +if [ "$this_mach" != "x86_64" ]; then + echo "$0: build was tested on x86_64, not on this <$this_mach>" 1>&2 +fi + +mach=${1:-${this_mach}} +libc=${2:-static} + +case "$mach" in + i686) + alpine=x86 # official: i386/alpine + ubuntu=x86 + busybox=i386 + ;; + x86_64) + alpine=x86_64 # official: amd64/alpine + ubuntu=x86_64 + busybox=amd64 + ;; + armv6l) + # For Raspberry 1 and Zero. + # Tested on Raspberry 1 B+ (BCM2835 rev. 0010). + alpine=armhf # official: arm32v6/alpine + ubuntu=* + busybox=arm32v6 + ;; + armv7l) + # For Raspberry 2 and 3. + # Tested on Raspberry 3 Model B (BCM2835 revision a02082). + # Tested on Raspberry 3 Model B+ (BCM2835 revision a020d3). + alpine=armv7 # official: arm32v7/alpine + ubuntu=armhf + busybox=arm32v7 + ;; + aarch64) + # For Raspberry 4? + alpine=arm64 # official: arm64v8/alpine + ubuntu=arm64 # or aarch64? See https://wiki.ubuntu.com/ARM/RaspberryPi#Ubuntu_arm64.2FAArch64 + busybox=arm64v8 + ;; *) - echo "$0: unknown arch <$arch>, known are: (native|x86|x86_64|arm64|armhf)" 1>&2 + echo "$0: unknown machine hardware name <$mach>, known are: {i686,x86_64,armv6l,armv7l,aarch64}" 1>&2 exit 1 esac -sed "s,^FROM ubuntu:bionic AS,FROM ${from} AS," Dockerfile.ubxtool | docker build -f - --tag ubxtool:${tag} . +case "$libc" in + static) + from="alpine:3.10" + to="multiarch/alpine:${alpine}-v3.10" + ;; + glibc) + if [ "$ubuntu" = "*" ]; then + echo "$0: unsupported combination of machine <$mach> and libc <$libc>" 1>&2 + exit 1 + fi + from="ubuntu:bionic" + to="multiarch/ubuntu-core:${ubuntu}-bionic" + ;; + *) + echo "$0: unknown libc <$libc>, known are: {static,glibc}" 1>&2 + exit 1 +esac + +tag="${mach}-${libc}" + +sed -e "s,^FROM ${from} AS ,FROM ${to} AS ," \ + -e "s,^FROM busybox:glibc,FROM ${busybox}/busybox:glibc," \ + Dockerfile.ubxtool.${libc} \ + | docker build -f - --tag ubxtool:${tag} . + cntr=$(docker create ubxtool:${tag}) -docker cp ${cntr}:/opt/ubxtool ./ubxtool.nodeps.${tag} +docker cp ${cntr}:/opt/ubxtool bin/ubxtool.${tag} docker rm ${cntr} diff --git a/ubxtool.cc b/ubxtool.cc index f9770b1..59d152e 100644 --- a/ubxtool.cc +++ b/ubxtool.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include "fmt/format.h" #include "fmt/printf.h" #include "bits.hh"