3434 runner : ubuntu-24.04
3535 arm32 : ' '
3636 with_mdns : ' ON'
37+ with_portaudio : ' ON'
3738 with_pulse : ' ON'
3839 with_pipewire : ' ON'
3940 expect_probe : ' Failed'
4849 runner : ubuntu-24.04-arm
4950 arm32 : ' '
5051 with_mdns : ' ON'
52+ with_portaudio : ' ON'
5153 with_pulse : ' ON'
5254 with_pipewire : ' ON'
5355 expect_probe : ' Failed'
6365 runner : ubuntu-24.04
6466 arm32 : ' armv7'
6567 with_mdns : ' ON'
68+ with_portaudio : ' ON'
6669 with_pulse : ' ON'
6770 with_pipewire : ' ON'
6871 expect_probe : ' Failed'
@@ -78,12 +81,13 @@ jobs:
7881 runner : macos-14
7982 arm32 : ' '
8083 with_mdns : ' ON'
84+ with_portaudio : ' OFF'
8185 with_pulse : ' OFF'
8286 with_pipewire : ' OFF'
8387 expect_probe : ' Success'
84- expect_backends : ' ^-- sendspin-cli audio backends: null, stdout, portaudio $'
88+ expect_backends : ' ^-- sendspin-cli audio backends: null, stdout, coreaudio $'
8589 expect_mdns : ' ^-- sendspin-cli mDNS: dns_sd \(Bonjour, built in\)$'
86- runtime_packages : ' portaudio (brew). Bonjour is part of macOS.'
90+ runtime_packages : ' none. CoreAudio, AudioToolbox and Bonjour are all part of macOS.'
8791 publish : true
8892 avahi : false
8993 systemd : false
9397 runner : ubuntu-24.04
9498 arm32 : ' '
9599 with_mdns : ' OFF'
100+ with_portaudio : ' ON'
96101 with_pulse : ' OFF'
97102 with_pipewire : ' OFF'
98103 expect_backends : ' ^-- sendspin-cli audio backends: null, stdout, alsa, portaudio$'
@@ -200,10 +205,6 @@ jobs:
200205 echo 'A 32-bit ARM binary runs on this host.'
201206 rm -f binfmt-probe binfmt-probe.c
202207
203- - name : Install build dependencies (macOS)
204- if : runner.os == 'macOS'
205- run : brew install portaudio pkgconf
206-
207208 # Fetched sources and subbuild stamps only, never build outputs; keyed per leg and by CMakeLists.txt.
208209 - name : Cache the fetched sources
209210 uses : actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
@@ -216,6 +217,7 @@ jobs:
216217 - name : Configure
217218 env :
218219 WITH_MDNS : ${{ matrix.with_mdns }}
220+ WITH_PORTAUDIO : ${{ matrix.with_portaudio }}
219221 WITH_PULSE : ${{ matrix.with_pulse }}
220222 WITH_PIPEWIRE : ${{ matrix.with_pipewire }}
221223 DEPS_DIR : ${{ github.workspace }}/.deps
@@ -226,6 +228,7 @@ jobs:
226228 -DCMAKE_BUILD_TYPE=Release
227229 -DSENDSPIN_CLI_WERROR=ON
228230 -DSENDSPIN_CLI_WITH_MDNS="$WITH_MDNS"
231+ -DSENDSPIN_CLI_WITH_PORTAUDIO="$WITH_PORTAUDIO"
229232 -DSENDSPIN_CLI_WITH_PULSE="$WITH_PULSE"
230233 -DSENDSPIN_CLI_WITH_PIPEWIRE="$WITH_PIPEWIRE"
231234 -DFETCHCONTENT_BASE_DIR="$DEPS_DIR"
@@ -552,6 +555,35 @@ jobs:
552555 exit 1
553556 }
554557
558+ # What would have caught the dyld abort: a Homebrew load command is a dependency no clean
559+ # Mac has, and CI never sees it because the runner installed it.
560+ - name : Assert the macOS binary loads nothing that is not part of macOS
561+ if : matrix.publish && runner.os == 'macOS'
562+ env :
563+ NAME : ${{ steps.package.outputs.name }}
564+ run : |
565+ binary="stage/$NAME/usr/local/bin/sendspin-cli"
566+ echo 'What the staged binary loads:'
567+ otool -L "$binary"
568+
569+ # Each dependency is a tab-indented line whose first field is the install name; the
570+ # header line naming the binary itself is not indented.
571+ otool -L "$binary" | sed -n 's|^\t\([^ ]*\).*|\1|p' >load-commands.txt
572+
573+ status=0
574+ while read -r path; do
575+ case "$path" in
576+ /usr/lib/*|/System/Library/Frameworks/*|/System/Library/PrivateFrameworks/*) ;;
577+ *)
578+ echo "::error::the binary loads $path, which is not part of macOS -- a Mac without it aborts at launch"
579+ status=1
580+ ;;
581+ esac
582+ done <load-commands.txt
583+
584+ rm -f load-commands.txt
585+ exit "$status"
586+
555587 # Install at the real prefix and verify the unit (not on cross legs: MemoryDenyWriteExecute= forbids qemu-user).
556588 # After Package, or a root-owned install manifest in build/ breaks the unprivileged staging install.
557589 - name : Install at the real prefix and verify the systemd unit
0 commit comments