Skip to content

Commit f4e5355

Browse files
committed
chore: overhaul cross-compilation helper
1 parent 25fa765 commit f4e5355

4 files changed

Lines changed: 117 additions & 160 deletions

File tree

.github/workflows/release.yml

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,59 +15,22 @@ jobs:
1515
runs-on: ubuntu-24.04
1616
strategy:
1717
matrix:
18-
include:
19-
- target: x86-64-linux-gnu
20-
goarch: amd64
21-
goamd64: v1
22-
cc: gcc
23-
tar: linux_x86_64
24-
- target: arm-rpi-linux-gnueabihf
25-
goarch: arm
26-
goarm: 6
27-
cc: arm-rpi-linux-gnueabihf-gcc
28-
tar: linux_armv6_rpi
29-
- target: arm-linux-gnueabihf
30-
goarch: arm
31-
goarm: 6
32-
cc: arm-linux-gnueabihf-gcc
33-
tar: linux_armv6
34-
- target: aarch64-linux-gnu
35-
goarch: arm64
36-
cc: aarch64-linux-gnu-gcc
37-
tar: linux_arm64
18+
variant: [ 'x86_64', 'arm64', 'armv6', 'armv6_rpi' ]
3819
steps:
39-
- uses: actions/checkout@v3
40-
with:
41-
fetch-depth: 0
42-
43-
- run: git fetch --force --tags
44-
45-
- name: Build image
46-
run: |
47-
docker build \
48-
--build-arg TARGET=${{ matrix.target }} \
49-
--build-arg GOARCH=${{ matrix.goarch }} \
50-
--build-arg GOARM=${{ matrix.goarm }} \
51-
--build-arg GOAMD64=${{ matrix.goamd64 }} \
52-
--build-arg CC=${{ matrix.cc }} \
53-
-t go-librespot-build-${{ matrix.target }} \
54-
-f Dockerfile.build \
55-
.
20+
- name: Checkout
21+
uses: actions/checkout@v3
5622

5723
- name: Compile binary
5824
run: |
5925
mkdir -p /tmp/out
60-
docker run --rm \
61-
--env COMMIT=${{ github.sha }} \
62-
--env VERSION=${{ startsWith(github.ref_name, 'v') && github.ref_name || '' }} \
63-
-v $PWD:/src \
64-
go-librespot-build-${{ matrix.target }}
65-
tar -zcvf /tmp/out/go-librespot_${{ matrix.tar }}.tar.gz go-librespot README.md
26+
./crosscompile.sh ${{ matrix.variant }}
27+
mv go-librespot-${{ matrix.variant }} go-librespot
28+
tar -zcvf /tmp/out/go-librespot_${{ matrix.variant }}.tar.gz go-librespot README.md
6629
6730
- name: Upload compiled binary
6831
uses: actions/upload-artifact@v4
6932
with:
70-
name: binaries-${{ matrix.target }}
33+
name: binaries-${{ matrix.variant }}
7134
path: /tmp/out
7235
retention-days: 7
7336

CROSS_COMPILE.md

Lines changed: 14 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,26 @@
11
# Cross Compiling
22

3-
Cross compilation is currently described for Linux only. All the commands below rely on the host platform being
4-
`linux/amd64`: this is currently enforced by the Dockerfile. If you are not on a `linux/amd64` system, have a look
5-
at [Multi-platform builds](https://docs.docker.com/build/building/multi-platform/).
3+
The cross compilation helper script uses Docker to build the project for different architectures with the respective
4+
toolchains.
65

7-
## Create Docker images for (cross-)compiling
6+
Currently, cross compilation is available only for Linux x64 hosts. This is enforced by Docker with the `--platform`
7+
flag set to `linux/amd64`. You can still use this helper on other platforms, but you will need to set up
8+
[Multi-platform builds](https://docs.docker.com/build/building/multi-platform/).
89

9-
### Target Linux x86_64
10+
## How To
1011

11-
```bash
12-
docker build \
13-
--build-arg TARGET=x86-64-linux-gnu \
14-
--build-arg GOARCH=amd64 \
15-
--build-arg GOAMD64=v1 \
16-
--build-arg CC=gcc \
17-
-f Dockerfile.build \
18-
-t go-librespot-build-x86_64 .
19-
```
20-
21-
### Target Linux on Raspberry Pi 1 / Zero
12+
A handy script to build the project for multiple platforms is provided [here](./crosscompile.sh). To use it simply
13+
specify the target variant you want to build for.
2214

2315
```bash
24-
docker build \
25-
--build-arg TARGET=arm-rpi-linux-gnueabihf \
26-
--build-arg GOARCH=arm \
27-
--build-arg GOARM=6 \
28-
--build-arg CC=arm-rpi-linux-gnueabihf-gcc \
29-
-f Dockerfile.build \
30-
-t go-librespot-build-armv6_rpi .
16+
./crosscompile.sh <variant>
3117
```
3218

33-
### Target Linux ARM32 (Raspberry Pi 2 and above)
19+
The currently supported variants are `x86_64`, `armv6`, `armv6_rpi` and `arm64`.
3420

35-
```bash
36-
docker build \
37-
--build-arg TARGET=arm-linux-gnueabihf \
38-
--build-arg GOARCH=arm \
39-
--build-arg GOARM=6 \
40-
--build-arg CC=arm-linux-gnueabihf-gcc \
41-
-f Dockerfile.build \
42-
-t go-librespot-build-armv6 .
43-
```
21+
## `armv6` vs `armv6_rpi`
4422

45-
### Target Linux ARM64
23+
The `armv6` variant is a generic armv6 build. It should work on most armv6 devices that support thumb instructions.
4624

47-
```bash
48-
docker build \
49-
--build-arg TARGET=aarch64-linux-gnu \
50-
--build-arg GOARCH=arm64 \
51-
--build-arg CC=aarch64-linux-gnu-gcc \
52-
-f Dockerfile.build \
53-
-t go-librespot-build-arm64 .
54-
```
55-
56-
## Use the images built above to (cross-)compile
57-
58-
`cd` into the root of the `go-librespot` source code and run on of the following statements.
59-
60-
### Target Linux x86_64
61-
62-
```bash
63-
docker run --rm -u $(id -u):$(id -g) -v $PWD:/src -e GOOUTSUFFIX=-x86_64 go-librespot-build-x86_64
64-
```
65-
66-
### Target Linux on Raspberry Pi 1 / Zero
67-
68-
```bash
69-
docker run --rm -u $(id -u):$(id -g) -v $PWD:/src -e GOOUTSUFFIX=-armv6_rpi go-librespot-build-armv6_rpi
70-
```
71-
72-
### Target Linux ARM32 (Raspberry Pi 2 and above)
73-
74-
```bash
75-
docker run --rm -u $(id -u):$(id -g) -v $PWD:/src -e GOOUTSUFFIX=-armv6 go-librespot-build-armv6
76-
```
77-
78-
### Target Linux ARM64
79-
80-
```bash
81-
docker run --rm -u $(id -u):$(id -g) -v $PWD:/src -e GOOUTSUFFIX=-arm64 go-librespot-build-arm64
82-
```
25+
The `armv6_rpi` variant is specifically built for the Raspberry Pi 1 and Zero, which do not support thumb instructions.
26+
The toolchain used for this build can be found [here](https://github.com/devgianlu/rpi-toolchain).

Dockerfile.build

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,43 @@
1-
FROM --platform=linux/amd64 docker.io/golang:1.22.2-bullseye
1+
FROM --platform=linux/amd64 docker.io/golang:1.22.2
22

3-
ENV COMMIT=dev
4-
ENV VERSION=0.0.0
3+
# Build tools
4+
RUN apt-get update && apt-get install -y zip autoconf autopoint libtool
55

6-
# Preparations
7-
RUN apt-get update && apt-get install -y wget build-essential
8-
9-
# Download and extract dependency sources
10-
RUN cd /tmp && \
11-
wget http://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.10.tar.bz2 && \
12-
tar -xvf alsa-lib-1.2.10.tar.bz2
13-
RUN cd /tmp && \
14-
wget https://downloads.xiph.org/releases/ogg/libogg-1.3.5.tar.xz && \
15-
tar -xvf libogg-1.3.5.tar.xz
16-
RUN cd /tmp && \
17-
wget https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz && \
18-
tar -xvf libvorbis-1.3.7.tar.xz
19-
20-
# Depencies arguments
6+
# Install toolchain
217
ARG TARGET
22-
ARG CC
23-
24-
# Install toolchain for anything besides arm-rpi-linux-gnueabihf
25-
RUN if [ ${TARGET} != arm-rpi-linux-gnueabihf ]; then \
26-
apt-get install -y gcc-${TARGET} ; \
27-
fi
28-
29-
# Install custom toolchain for arm-rpi-linux-gnueabihf
30-
RUN if [ ${TARGET} = arm-rpi-linux-gnueabihf ]; then \
8+
RUN if [ "$TARGET" = "arm-rpi-linux-gnueabihf" ]; then \
319
cd /tmp && \
3210
wget https://github.com/devgianlu/rpi-toolchain/releases/download/v1/arm-rpi-linux-gnueabihf.tar.gz && \
3311
tar -C /usr --strip-components=1 -xzf arm-rpi-linux-gnueabihf.tar.gz ; \
12+
else \
13+
apt-get install -y "gcc-$TARGET" ; \
3414
fi
3515

36-
# Compile dependency sources
37-
RUN cd /tmp/alsa-lib-1.2.10 && \
38-
./configure --enable-shared=yes --enable-static=no --with-pic --host=${TARGET} --prefix=/tmp/deps/${TARGET} && \
39-
make -j $(nproc) && make install
40-
RUN cd /tmp/libogg-1.3.5 && \
41-
./configure --host=${TARGET} --prefix=/tmp/deps/${TARGET} && \
42-
make -j $(nproc) && make install
43-
RUN cd /tmp/libvorbis-1.3.7 && \
44-
./configure --host=${TARGET} --prefix=/tmp/deps/${TARGET} && \
45-
make -j $(nproc) && make install
46-
47-
# Golang arguments
16+
# Move to build directory
17+
WORKDIR /build
18+
19+
# Setup vcpkg
20+
ADD https://github.com/microsoft/vcpkg.git#2025.09.17 vcpkg
21+
RUN cd vcpkg && ./bootstrap-vcpkg.sh
22+
ENV VCPKG_ROOT=/build/vcpkg
23+
ENV PATH="$VCPKG_ROOT:$PATH"
24+
25+
# Compile dependencies
26+
ARG TRIPLET
27+
COPY vcpkg.json vcpkg-configuration.json ./
28+
COPY vcpkg-triplets ./vcpkg-triplets
29+
RUN --mount=type=cache,target=/build/vcpkg/downloads \
30+
--mount=type=cache,target=/build/vcpkg/buildtrees \
31+
vcpkg install --triplet "$TRIPLET"
32+
33+
# Go compilation setup
34+
ARG GOCC
4835
ARG GOARCH
4936
ARG GOAMD64
5037
ARG GOARM
5138

52-
# Compile
5339
WORKDIR /src
54-
ENV CGO_ENABLED=1 PKG_CONFIG_PATH=/tmp/deps/${TARGET}/lib/pkgconfig/ CC=${CC} \
55-
GOARCH=${GOARCH} GOAMD64=${GOAMD64} GOARM=${GOARM} GOOUTSUFFIX='' \
40+
ENV CGO_ENABLED=1 PKG_CONFIG_PATH="/build/vcpkg_installed/$TRIPLET/lib/pkgconfig" CC="$GOCC" \
41+
GOARCH="$GOARCH" GOAMD64="$GOAMD64" GOARM="$GOARM" \
5642
GOCACHE=/src/.gocache/go-build GOMODCACHE=/src/.gocache/mod
57-
CMD go build \
58-
-buildvcs=false \
59-
-ldflags="-X github.com/devgianlu/go-librespot.commit=${COMMIT} -X github.com/devgianlu/go-librespot.version=${VERSION}" \
60-
-o ./go-librespot${GOOUTSUFFIX} -a ./cmd/daemon
43+
CMD ["go", "build", "-o", "./go-librespot", "-a", "-ldflags", "-s -w", "./cmd/daemon"]

crosscompile.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
3+
set -eux
4+
5+
VARIANT="${1:-}"
6+
if [ -z "$VARIANT" ]; then
7+
echo "Usage: $0 (x86_64|armv6|armv6_rpi|arm64)"
8+
exit 1
9+
fi
10+
11+
# Validate and map variant to compilation envs
12+
if [ "$VARIANT" = "x86_64" ]; then
13+
TARGET="x86-64-linux-gnu"
14+
TRIPLET="x64-linux"
15+
GOARCH="amd64"
16+
GOAMD64="v1"
17+
GOARM=""
18+
GOCC="gcc"
19+
elif [ "$VARIANT" = "armv6" ]; then
20+
TARGET="arm-linux-gnueabihf"
21+
TRIPLET="arm-linux"
22+
GOARCH="arm"
23+
GOAMD64=""
24+
GOARM="6"
25+
GOCC="arm-linux-gnueabihf-gcc"
26+
elif [ "$VARIANT" = "armv6_rpi" ]; then
27+
TARGET="arm-rpi-linux-gnueabihf"
28+
TRIPLET="arm-linux-rpi"
29+
GOARCH="arm"
30+
GOAMD64=""
31+
GOARM="6"
32+
GOCC="arm-rpi-linux-gnueabihf-gcc"
33+
elif [ "$VARIANT" = "arm64" ]; then
34+
TARGET="aarch64-linux-gnu"
35+
TRIPLET="arm64-linux"
36+
GOARCH="arm64"
37+
GOAMD64=""
38+
GOARM=""
39+
GOCC="aarch64-linux-gnu-gcc"
40+
else
41+
echo "Unsupported variant: $VARIANT"
42+
exit 1
43+
fi
44+
45+
DOCKER_IMAGE_NAME="go-librespot-build-${VARIANT}"
46+
47+
# Build the image for cross-compilation
48+
docker build \
49+
--build-arg "TARGET=$TARGET" \
50+
--build-arg "TRIPLET=$TRIPLET" \
51+
--build-arg "GOARCH=$GOARCH" \
52+
--build-arg "GOAMD64=$GOAMD64" \
53+
--build-arg "GOARM=$GOARM" \
54+
--build-arg "GOCC=$GOCC" \
55+
-f Dockerfile.build \
56+
-t "$DOCKER_IMAGE_NAME" \
57+
.
58+
59+
# Build go-librespot using the cross-compilation image
60+
docker run --rm \
61+
-u "$(id -u):$(id -g)" \
62+
-v "$PWD":/src \
63+
"$DOCKER_IMAGE_NAME"
64+
65+
# Print info about the built binary
66+
mv "./go-librespot" "./go-librespot-$VARIANT"
67+
file "./go-librespot-$VARIANT"

0 commit comments

Comments
 (0)