Skip to content

Commit e35438d

Browse files
authored
Merge pull request #23 from music-assistant/build-setup
Add automated build + fix macos
2 parents d8f843b + 159c076 commit e35438d

File tree

10 files changed

+2427
-15
lines changed

10 files changed

+2427
-15
lines changed

.github/workflows/build.yml

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
name: Build cliap2 for all supported platforms
2+
3+
on:
4+
push:
5+
branches: [main, dev]
6+
pull_request:
7+
branches: [main, dev]
8+
workflow_dispatch:
9+
10+
jobs:
11+
linux-x86_64:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
with:
17+
submodules: recursive
18+
19+
- name: Apply FFmpeg 8.0 compatibility patch
20+
run: |
21+
cat > /tmp/ffmpeg8.patch << 'EOF'
22+
--- a/owntone-server/src/transcode.c
23+
+++ b/owntone-server/src/transcode.c
24+
@@ -1441,8 +1441,10 @@ transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality
25+
// If the source has REPLAYGAIN_TRACK_GAIN metadata, this will inject the
26+
// values into the the next packet's side data (as AV_FRAME_DATA_REPLAYGAIN),
27+
// which has the effect that a volume replaygain filter works. Note that
28+
// ffmpeg itself uses another method in process_input() in ffmpeg.c.
29+
+#if LIBAVFORMAT_VERSION_MAJOR < 60
30+
av_format_inject_global_side_data(ctx->ifmt_ctx);
31+
+#endif
32+
33+
ret = avformat_find_stream_info(ctx->ifmt_ctx, NULL);
34+
if (ret < 0)
35+
EOF
36+
patch -p1 < /tmp/ffmpeg8.patch
37+
38+
- name: Install build dependencies
39+
run: |
40+
sudo apt-get update
41+
sudo apt-get install -y \
42+
build-essential git autotools-dev autoconf automake libtool gettext gawk gperf \
43+
libconfuse-dev libunistring-dev \
44+
libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev \
45+
libasound2-dev libxml2-dev libgcrypt20-dev zlib1g-dev \
46+
libevent-dev libplist-dev libsodium-dev libjson-c-dev \
47+
libcurl4-openssl-dev libprotobuf-c-dev pkg-config bison flex
48+
49+
- name: Build for x86_64
50+
run: |
51+
autoreconf -fi
52+
./configure
53+
make -j$(nproc)
54+
mkdir -p release
55+
cp src/cliap2 release/cliap2-linux-x86_64
56+
chmod +x release/cliap2-linux-x86_64
57+
# Show file type and dependencies
58+
file release/cliap2-linux-x86_64
59+
ldd release/cliap2-linux-x86_64
60+
61+
- name: Upload artifacts
62+
uses: actions/upload-artifact@v4
63+
with:
64+
name: cliap2-linux-x86_64
65+
path: release/
66+
67+
linux-aarch64:
68+
runs-on: ubuntu-24.04-arm
69+
steps:
70+
- name: Checkout
71+
uses: actions/checkout@v4
72+
with:
73+
submodules: recursive
74+
75+
- name: Apply FFmpeg 8.0 compatibility patch
76+
run: |
77+
cat > /tmp/ffmpeg8.patch << 'EOF'
78+
--- a/owntone-server/src/transcode.c
79+
+++ b/owntone-server/src/transcode.c
80+
@@ -1441,8 +1441,10 @@ transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality
81+
// If the source has REPLAYGAIN_TRACK_GAIN metadata, this will inject the
82+
// values into the the next packet's side data (as AV_FRAME_DATA_REPLAYGAIN),
83+
// which has the effect that a volume replaygain filter works. Note that
84+
// ffmpeg itself uses another method in process_input() in ffmpeg.c.
85+
+#if LIBAVFORMAT_VERSION_MAJOR < 60
86+
av_format_inject_global_side_data(ctx->ifmt_ctx);
87+
+#endif
88+
89+
ret = avformat_find_stream_info(ctx->ifmt_ctx, NULL);
90+
if (ret < 0)
91+
EOF
92+
patch -p1 < /tmp/ffmpeg8.patch
93+
94+
- name: Install build dependencies
95+
run: |
96+
sudo apt-get update
97+
sudo apt-get install -y \
98+
build-essential git autotools-dev autoconf automake libtool gettext gawk gperf \
99+
libconfuse-dev libunistring-dev \
100+
libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev \
101+
libasound2-dev libxml2-dev libgcrypt20-dev zlib1g-dev \
102+
libevent-dev libplist-dev libsodium-dev libjson-c-dev \
103+
libcurl4-openssl-dev libprotobuf-c-dev pkg-config bison flex
104+
105+
- name: Build for ARM64
106+
run: |
107+
autoreconf -fi
108+
./configure
109+
make -j$(nproc)
110+
mkdir -p release
111+
cp src/cliap2 release/cliap2-linux-aarch64
112+
chmod +x release/cliap2-linux-aarch64
113+
# Show file type and dependencies
114+
file release/cliap2-linux-aarch64
115+
ldd release/cliap2-linux-aarch64
116+
117+
- name: Upload artifacts
118+
uses: actions/upload-artifact@v4
119+
with:
120+
name: cliap2-linux-aarch64
121+
path: release/
122+
123+
macos:
124+
runs-on: macos-14
125+
steps:
126+
- name: Checkout
127+
uses: actions/checkout@v4
128+
with:
129+
submodules: recursive
130+
131+
- name: Apply FFmpeg 8.0 compatibility patch
132+
run: |
133+
cat > /tmp/ffmpeg8.patch << 'EOF'
134+
--- a/owntone-server/src/transcode.c
135+
+++ b/owntone-server/src/transcode.c
136+
@@ -1441,8 +1441,10 @@ transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality
137+
// If the source has REPLAYGAIN_TRACK_GAIN metadata, this will inject the
138+
// values into the the next packet's side data (as AV_FRAME_DATA_REPLAYGAIN),
139+
// which has the effect that a volume replaygain filter works. Note that
140+
// ffmpeg itself uses another method in process_input() in ffmpeg.c.
141+
+#if LIBAVFORMAT_VERSION_MAJOR < 60
142+
av_format_inject_global_side_data(ctx->ifmt_ctx);
143+
+#endif
144+
145+
ret = avformat_find_stream_info(ctx->ifmt_ctx, NULL);
146+
if (ret < 0)
147+
EOF
148+
patch -p1 < /tmp/ffmpeg8.patch
149+
150+
- name: Install build dependencies
151+
run: |
152+
brew install \
153+
autoconf automake libtool gettext gawk pkg-config \
154+
confuse libunistring ffmpeg libxml2 libgcrypt zlib libevent libplist \
155+
libsodium json-c curl openssl@3 protobuf-c bison libiconv
156+
157+
- name: Build for macOS ARM64
158+
run: |
159+
export PATH="$(brew --prefix bison)/bin:$PATH"
160+
export OPENSSL_PREFIX="$(brew --prefix openssl@3)"
161+
export LIBXML2_PREFIX="$(brew --prefix libxml2)"
162+
export ZLIB_PREFIX="$(brew --prefix zlib)"
163+
export LIBGCRYPT_PREFIX="$(brew --prefix libgcrypt)"
164+
export LIBGPG_ERROR_PREFIX="$(brew --prefix libgpg-error)"
165+
export LIBUNISTRING_PREFIX="$(brew --prefix libunistring)"
166+
export LIBICONV_PREFIX="$(brew --prefix libiconv)"
167+
168+
# Static linking for OpenSSL
169+
export PKG_CONFIG_PATH="$LIBXML2_PREFIX/lib/pkgconfig:$ZLIB_PREFIX/lib/pkgconfig:$LIBGCRYPT_PREFIX/lib/pkgconfig:$LIBGPG_ERROR_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
170+
export LDFLAGS="-L$LIBXML2_PREFIX/lib -L$ZLIB_PREFIX/lib -L$LIBGCRYPT_PREFIX/lib -L$LIBGPG_ERROR_PREFIX/lib -L$LIBICONV_PREFIX/lib"
171+
export CPPFLAGS="-I$OPENSSL_PREFIX/include -I$LIBXML2_PREFIX/include -I$ZLIB_PREFIX/include -I$LIBGCRYPT_PREFIX/include -I$LIBGPG_ERROR_PREFIX/include -I$LIBICONV_PREFIX/include"
172+
export LIBUNISTRING_CFLAGS="-I$LIBUNISTRING_PREFIX/include"
173+
export LIBUNISTRING_LIBS="-L$LIBUNISTRING_PREFIX/lib -lunistring -L$LIBICONV_PREFIX/lib -liconv"
174+
175+
# Add static OpenSSL libraries to LIBS
176+
export LIBS="$OPENSSL_PREFIX/lib/libssl.a $OPENSSL_PREFIX/lib/libcrypto.a"
177+
178+
autoreconf -fi
179+
./configure || { echo "Configure failed, showing config.log:"; tail -100 config.log; exit 1; }
180+
make -j$(sysctl -n hw.ncpu)
181+
mkdir -p release
182+
cp src/cliap2 release/cliap2-macos-arm64
183+
chmod +x release/cliap2-macos-arm64
184+
# Show dependencies - verify OpenSSL is statically linked
185+
echo "=== Binary dependencies ==="
186+
otool -L release/cliap2-macos-arm64
187+
echo "=== Checking for OpenSSL symbols ==="
188+
nm release/cliap2-macos-arm64 | grep -i ssl | head -10 || echo "OpenSSL symbols found (statically linked)"
189+
190+
- name: Upload artifacts
191+
uses: actions/upload-artifact@v4
192+
with:
193+
name: cliap2-macos-arm64
194+
path: release/
195+
196+
create-release:
197+
needs: [linux-x86_64, linux-aarch64, macos]
198+
runs-on: ubuntu-latest
199+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')
200+
steps:
201+
- name: Download all artifacts
202+
uses: actions/download-artifact@v4
203+
with:
204+
path: artifacts
205+
206+
- name: Display structure of downloaded files
207+
run: ls -R artifacts
208+
209+
- name: Create Release
210+
uses: softprops/action-gh-release@v1
211+
with:
212+
tag_name: build-${{ github.sha }}
213+
name: Automated Build ${{ github.sha }}
214+
draft: false
215+
prerelease: true
216+
files: |
217+
artifacts/cliap2-linux-x86_64/*
218+
artifacts/cliap2-linux-aarch64/*
219+
artifacts/cliap2-macos-arm64/*
220+
env:
221+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Command line interface for audio streaming to AirPlay 2 devices
44

55
Based on [owntones](https://github.com/owntone/owntone-server) (all rights reserved).
66

7+
## Pre-built binaries
8+
9+
Pre-built binaries for Linux (x86_64 and ARM64) and macOS (Apple Silicon/ARM64) are automatically built via GitHub Actions and available as build artifacts on the repository.
10+
711
## Debian build
812

913
NOTE: This is in early stage development and will be subject to change.
@@ -48,39 +52,51 @@ Visit https://brew.sh/ and follow the instructions. Alternatively run the instal
4852
3. Install required Homebrew packages. This installs the closest macOS equivalents to the Debian packages listed above:
4953

5054
```zsh
51-
brew update
5255
brew install git autoconf automake libtool gettext gawk pkg-config \
53-
libconfuse libunistring ffmpeg libxml2 libgcrypt zlib libevent libplist \
54-
libsodium json-c curl openssl@1.1 protobuf-c
56+
confuse libunistring ffmpeg libxml2 libgcrypt zlib libevent libplist \
57+
libsodium json-c curl openssl@3 protobuf-c bison
5558
```
5659

5760
Notes:
5861

59-
- Replace `[email protected]` with `openssl` if you want OpenSSL 3. Use `brew info openssl` to check versions.
62+
- OpenSSL 3 is recommended as OpenSSL 1.1 reached end-of-life in September 2023.
63+
- Bison from Homebrew is required as macOS ships with an outdated version (2.3).
6064
- macOS uses CoreAudio instead of ALSA (`libasound2-dev`). The project should detect and skip ALSA on macOS; if it doesn't, look for a configure flag to disable ALSA support.
6165

62-
4. Export Homebrew paths so `./configure` finds brewed libraries (portable for Intel/Apple Silicon):
66+
4. Export Homebrew paths so `./configure` finds libraries (portable for Intel/Apple Silicon):
6367

6468
```zsh
6569
export BREW_PREFIX="$(brew --prefix)"
66-
export OPENSSL_PREFIX="$(brew --prefix openssl@1.1)" # or $(brew --prefix openssl)
70+
export OPENSSL_PREFIX="$(brew --prefix openssl@3)"
6771
export LIBXML2_PREFIX="$(brew --prefix libxml2)"
6872
export ZLIB_PREFIX="$(brew --prefix zlib)"
69-
70-
export PKG_CONFIG_PATH="$OPENSSL_PREFIX/lib/pkgconfig:$LIBXML2_PREFIX/lib/pkgconfig:$ZLIB_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
71-
export LDFLAGS="-L$OPENSSL_PREFIX/lib -L$LIBXML2_PREFIX/lib -L$ZLIB_PREFIX/lib $LDFLAGS"
72-
export CPPFLAGS="-I$OPENSSL_PREFIX/include -I$LIBXML2_PREFIX/include -I$ZLIB_PREFIX/include $CPPFLAGS"
73+
export LIBGCRYPT_PREFIX="$(brew --prefix libgcrypt)"
74+
export LIBGPG_ERROR_PREFIX="$(brew --prefix libgpg-error)"
75+
export LIBUNISTRING_PREFIX="$(brew --prefix libunistring)"
76+
export LIBICONV_PREFIX="$(brew --prefix libiconv)"
77+
78+
export PKG_CONFIG_PATH="$LIBXML2_PREFIX/lib/pkgconfig:$ZLIB_PREFIX/lib/pkgconfig:$LIBGCRYPT_PREFIX/lib/pkgconfig:$LIBGPG_ERROR_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
79+
export LDFLAGS="-L$LIBXML2_PREFIX/lib -L$ZLIB_PREFIX/lib -L$LIBGCRYPT_PREFIX/lib -L$LIBGPG_ERROR_PREFIX/lib -L$LIBICONV_PREFIX/lib"
80+
export CPPFLAGS="-I$OPENSSL_PREFIX/include -I$LIBXML2_PREFIX/include -I$ZLIB_PREFIX/include -I$LIBGCRYPT_PREFIX/include -I$LIBGPG_ERROR_PREFIX/include -I$LIBICONV_PREFIX/include"
81+
export LIBUNISTRING_CFLAGS="-I$LIBUNISTRING_PREFIX/include"
82+
export LIBUNISTRING_LIBS="-L$LIBUNISTRING_PREFIX/lib -lunistring -L$LIBICONV_PREFIX/lib -liconv"
83+
export PATH="/opt/homebrew/opt/bison/bin:$PATH"
84+
85+
# For static linking of OpenSSL (recommended for distribution)
86+
export LIBS="$OPENSSL_PREFIX/lib/libssl.a $OPENSSL_PREFIX/lib/libcrypto.a"
7387
```
7488

7589
5. Build the project:
7690

7791
```zsh
7892
git submodule update --init
79-
autoreconf -i
93+
autoreconf -fi
8094
./configure
8195
make
8296
```
8397

98+
The binary will be created at `src/cliap2`.
99+
84100
If `./configure` fails to find libraries, check the `PKG_CONFIG_PATH` and the `--with-...` flags in `./configure --help` and point them to the Homebrew prefixes above.
85101

86102
Troubleshooting:

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ AC_PROG_CC
1818
AC_PROG_CC_C_O
1919
AC_PROG_SED
2020
AC_PROG_MKDIR_P
21-
LT_INIT([disable-static])
21+
LT_INIT([])
2222

2323
AC_PATH_PROG([GPERF], [[gperf]])
2424
AS_IF([[test -z "$GPERF"]],

0 commit comments

Comments
 (0)