2

Background

I'm writing an open-source GTK go app subsonic API client which:

  • targets on first place mobile friendly Linux like postmarketOS (alpine linux), Mobian (debian)
  • in future will be also extended to desktop Linux, Windows and Mac OS but not Android or iOS as they already have one.
  • needs to be available at least on aarch64 and x86_64
  • depends on native libs like portaudio, libasound, libopus
  • so it needs CGO to be enabled

I haven't published app yet as I self-host my git and I have to do some additional config. It won't be available until late october 2021.

App successfully compiles (on host) and runs on my main PC which is x86_64 fedora.

App successfully compiles (on docker) and runs on aarch64 glibc distros like Mobian

This is Dockerfile:

FROM golang:1.17-bullseye
LABEL os=linux
LABEL arch=arm64
ENV GOOS=linux
ENV GOARCH=arm64
ENV CGO_ENABLED=1
ENV CC=aarch64-linux-gnu-gcc
ENV PATH="/go/bin/${GOOS}_${GOARCH}:${PATH}"
ENV PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig
# install build & runtime dependencies
RUN dpkg --add-architecture arm64 
RUN apt update && apt upgrade -y 
RUN apt install -y --no-install-recommends \
        protobuf-compiler \
        upx \
        gcc-aarch64-linux-gnu \
        libc6-dev-arm64-cross \
        pkg-config \
        libasound2-dev:arm64 \
        libgtk-3-dev:arm64 \
        libcairo2-dev:arm64 \
        libglib2.0-dev:arm64 \
        libgdk-pixbuf2.0-dev:arm64 \
        libsamplerate0:arm64 \
        libsamplerate0-dev:arm64 \
        libopusfile0:arm64 \
        libopusfile-dev:arm64 \
        libopus0:arm64 \
        libopus-dev:arm64 \
        libportaudio2:arm64 \
        portaudio19-dev:arm64 
# install build dependencies (code generators)
RUN go get github.com/hajimehoshi/oto \
    && go get github.com/faiface/beep \
    && go get github.com/faiface/beep/flac \
    && go get github.com/faiface/beep/speaker \
    && go get github.com/faiface/beep/mp3 \
    && go get github.com/faiface/beep/vorbis \
    && go get github.com/faiface/beep/wav\
    && go get github.com/gotk3/gotk3 \
    && go get github.com/delucks/go-subsonic \
    && go get github.com/hashicorp/go-retryablehttp \
    && go get github.com/zalando/go-keyring \
    && go get github.com/emirpasic/gods/lists/ \
    && go get github.com/emirpasic/gods/lists/arraylist \

Problems

  1. I can't run Mobian working binary on postmarketOS as alpine linux uses musl instead. file output is: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, (...) for GNU/Linux 3.7.0. not stripped.
  2. I haven't manged to use musl toolchain in docker debian as it is 32 binary executable and image is 64 bit.
  3. I couldn't find anything about multiarch in alpine so probably I can't use docker image goalng:1.17-alpine on x86_64 (I'd have also to find native libs packaged)

I wish it's just problem with my config, if it's possible I'd love solution with docker as I'd like to use CI/CD in future.

Resources, ideas, workarounds

  • I have raspberry pi with debian installed with some services. I could use with native musl toolchain and debian aarch64 docker container but it's not handy in production pipeline. Also, I haven't tried this.

Good to read

  1. Crosscompile CGO projects (also with docker)
  2. Crosscompile with cross-platform musl toolchains
  3. Related stackoverflow thread about alpine linux and go binaries

1 Answer 1

0

I had a similar problem where I needed to build a static Go binary with cgo that would eventually run in an alpine container with arm64 architecture, but had to be built in a golang:alpine container with x86_64 architecture (I didn't have control over the CI/CD runner architecture).

I got it to work by downloading a cross-compiler (CC) and specifying that it be used during the Go build.

Here is an example of downloading/extracting the CC in the container user's home directory and using it in a go build based out of /usr/src/example that produces an executable named exampleApp.

wget -P ~ https://musl.cc/aarch64-linux-musl-cross.tgz
tar -xvf ~/aarch64-linux-musl-cross.tgz -C ~
cd /usr/src/example
GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=~/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc go build -o exampleApp -a -ldflags=-extldflags=-static . 

Running file on the exe output verified it was statically linked for aarch64. I was then able to run it in an arm64 alpine container elsewhere.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .