Skip to content

Commit 3db4639

Browse files
Copilotwinnerspiros
andauthored
Fix bass DllNotFoundException + harden APK verification + merge upstream master
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/1e7cb6f9-16ce-458e-921d-22823a0b1260 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
1 parent 00e1879 commit 3db4639

2 files changed

Lines changed: 76 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,48 @@ jobs:
280280
exit 1
281281
fi
282282
283+
# Architecture sanity check: a previous build packaged the Linux-glibc
284+
# libbass.so from ppy.osu.Framework.NativeLibs into lib/arm64-v8a/, which
285+
# passed the name check above but failed at runtime with
286+
# System.DllNotFoundException: bass because Android's bionic linker cannot
287+
# resolve glibc-only symbols. Both Linux and Android builds report
288+
# identically as "ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV)"
289+
# via file(1), so we rely on the presence of GLIBC_ versioned symbols
290+
# (which exist only in glibc-linked binaries) to distinguish them.
283291
echo ""
284-
echo "All required native libraries present ✓"
292+
echo "Verifying native library architectures (must be Android arm64, not Linux glibc)..."
293+
TMPDIR=$(mktemp -d)
294+
trap 'rm -rf "$TMPDIR"' EXIT
295+
BAD=0
296+
for LIB in libbass.so libbass_fx.so libbassmix.so; do
297+
unzip -p "$APK" "lib/arm64-v8a/$LIB" > "$TMPDIR/$LIB"
298+
FILE_INFO=$(file "$TMPDIR/$LIB")
299+
echo " $LIB: $FILE_INFO"
300+
# Must be a 64-bit aarch64 ELF shared object.
301+
if ! echo "$FILE_INFO" | grep -qE "ELF 64-bit.*aarch64|ELF 64-bit.*ARM aarch64"; then
302+
echo "::error::$LIB is not a 64-bit aarch64 ELF — runtime DllNotFoundException will occur."
303+
BAD=1
304+
continue
305+
fi
306+
# Reliable Linux-vs-Android distinguisher: GLIBC_ versioned symbols
307+
# (e.g. memcpy@@GLIBC_2.17) appear only in glibc-linked Linux binaries.
308+
# Android's bionic libc uses no symbol versioning.
309+
if strings "$TMPDIR/$LIB" | grep -q "^GLIBC_"; then
310+
echo "::error::$LIB references GLIBC_ versioned symbols — this is the Linux ELF from ppy.osu.Framework.NativeLibs runtimes/linux-arm64/native/, not the Android ELF from ppy.osu.Framework.Android. Android's bionic linker cannot load it; the app will crash at startup with System.DllNotFoundException: bass."
311+
BAD=1
312+
continue
313+
fi
314+
echo " ✅ $LIB is a valid Android arm64 ELF"
315+
done
316+
317+
if [ "$BAD" -ne 0 ]; then
318+
echo ""
319+
echo "::error::One or more native libraries in the APK are NOT valid Android arm64 binaries. This usually means desktop runtime .so files (e.g. from ppy.osu.Framework.NativeLibs runtimes/linux-arm64/native/) leaked into lib/arm64-v8a/ during packaging. See osu.Android.props FixRuntimePackAssetTypes target."
320+
exit 1
321+
fi
322+
323+
echo ""
324+
echo "All required native libraries present and valid ✓"
285325
286326
- name: Upload APK artifact
287327
uses: actions/upload-artifact@v7

osu.Android.props

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,46 @@
8282
Only .so files need the AssetType override — the previous broader filter
8383
(all non-DLL, non-PDB) incorrectly reclassified signing metadata and config
8484
files, which corrupted the APK signature (INSTALL_PARSE_FAILED_NO_CERTIFICATES).
85-
Scoped to Release only to avoid interfering with Debug builds. -->
85+
Scoped to Release only to avoid interfering with Debug builds.
86+
87+
IMPORTANT: only Android-runtime .so files may be marked as native and packaged
88+
into the APK. ppy.osu.Framework transitively depends on ppy.osu.Framework.NativeLibs
89+
which ships desktop-only natives under runtimes/linux-arm64/native/, runtimes/osx/native/,
90+
runtimes/win-*/native/ etc. — including a bare libbass.so, libbass_fx.so, libbassmix.so
91+
for Linux. If any of those are marked AssetType=native, the .NET Android SDK packs them
92+
into lib/arm64-v8a/ of the APK, racing with (and replacing) the proper Android arm64
93+
libbass*.so coming from ppy.osu.Framework.Android's AAR (jni/arm64-v8a/). The Linux ELF
94+
is linked against glibc and cannot be loaded by Android's bionic dynamic linker, which
95+
surfaces at startup as System.DllNotFoundException: bass from AudioManager..ctor →
96+
ManagedBass.Bass.get_DeviceCount, immediately crashing the app. -->
8697
<Target Name="FixRuntimePackAssetTypes" AfterTargets="ResolveRuntimePackAssets;ComputeFilesToPublish;ComputeResolvedFilesToPublishList"
8798
Condition="'$(Configuration)' == 'Release'">
8899
<ItemGroup>
89-
<RuntimePackAsset Update="@(RuntimePackAsset)" Condition="'%(Extension)' == '.so'">
100+
<!-- Strip desktop/iOS runtime .so files from the Android publish set entirely.
101+
Match path components for any non-Android RID known to ship .so files.
102+
Path normalisation handles both Windows (\) and Unix (/) separators. -->
103+
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)"
104+
Condition="'%(Extension)' == '.so'
105+
AND ($([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/linux-'))
106+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/linux/'))
107+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/osx-'))
108+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/osx/'))
109+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/ios-'))
110+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/ios/'))
111+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/maccatalyst-'))
112+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/win-'))
113+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/win/'))
114+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/browser-'))
115+
OR $([System.String]::Copy('%(Identity)').Replace('\','/').Contains('/runtimes/freebsd-')))" />
116+
<!-- Only mark Android-RID runtime pack assets as native. RuntimePackAsset items carry
117+
an explicit RuntimeIdentifier metadata, so this filter is exact. -->
118+
<RuntimePackAsset Update="@(RuntimePackAsset)"
119+
Condition="'%(Extension)' == '.so'
120+
AND $([System.String]::Copy('%(RuntimeIdentifier)').StartsWith('android'))">
90121
<AssetType>native</AssetType>
91122
</RuntimePackAsset>
123+
<!-- Mark the surviving (Android-only after the Remove above) publish .so files as native
124+
so the Android SDK packs them into lib/<abi>/ rather than dropping them as data. -->
92125
<ResolvedFileToPublish Update="@(ResolvedFileToPublish)" Condition="'%(Extension)' == '.so'">
93126
<AssetType>native</AssetType>
94127
</ResolvedFileToPublish>

0 commit comments

Comments
 (0)