4.6 KiB
Linux BSIPA Build Reference
Source Notes
This workflow comes from /home/pleb/ops/beatsaber/setlist/docs/pc-modding.md and /home/pleb/ops/beatsaber/setlist/docs/bootstrap.md. Prefer those local files and local clones under ~/src over web copies when deeper reference material is needed.
Toolchain
- PC BSIPA plugins are usually .NET Framework
net472class libraries. - Linux
dotnetSDK 6+ can build them because output DLLs are platform-agnostic CIL loaded by Beat Saber under Proton. BeatSaberModdingTools.Taskssupplies the MSBuild targets normally driven by Visual Studio/Rider BSMT extensions.- On this host,
dotnet --list-sdksshould show a usable SDK. NuGet is available for package inspection.
Game References
Point BeatSaberDir at a modded BSManager instance containing:
Beat Saber.exe
Beat Saber_Data/Managed/
IPA/
Libs/
Plugins/
winhttp.dll
Preferred local managed instance root:
/home/pleb/.local/share/BSManager/BSInstances/<version>
Windows mirror root:
/home/pleb/Windows/Users/pleb/BSManager/BSInstances/<version>
Use BeatSaberVersion.txt for the exact game version. The manifest gameVersion normally uses the major.minor.patch prefix, not the build suffix.
Project Configuration
Prefer machine-local configuration in <Project>.csproj.user:
<Project>
<PropertyGroup>
<BeatSaberDir>/home/pleb/.local/share/BSManager/BSInstances/1.40.8</BeatSaberDir>
</PropertyGroup>
</Project>
Some projects use LocalRefsDir and set:
<BeatSaberDir>$(LocalRefsDir)</BeatSaberDir>
For those, pass -p:LocalRefsDir=/path/to/instance or add a local .csproj.user property if the project imports it.
When changing a project file for Linux portability, prefer the smallest explicit fix:
- Add
Microsoft.NETFramework.ReferenceAssemblies.net472when MSBuild reports missing .NET Framework reference assemblies. - Set or pass
DisableCopyToPlugins=Truefor artifact-only builds. - Keep hint paths rooted at
$(BeatSaberDir)where possible. - Do not add broad multi-version compatibility logic unless requested.
Build Commands
From the plugin checkout:
dotnet restore <solution-or-project>
dotnet build <solution-or-project> -c Release -p:DisableCopyToPlugins=True
For a Debug smoke build:
dotnet build <solution-or-project> -c Debug -p:DisableCopyToPlugins=True
Expected outputs:
bin/Debug/<Plugin>.dll
bin/Release/<Plugin>.dll
bin/Release/zip/<Plugin>-<version>.zip
bin/<Configuration>/Artifact/Plugins/<Plugin>.dll
The exact layout depends on BSMT version and project customization.
BSMT Copy Behavior
BeatSaberModdingTools.Tasks may copy built DLLs into the game directory. On Unix hosts, its process check can behave differently and some projects add a custom target to copy into <BeatSaberDir>/Plugins/.
For builds that should not alter a live instance, pass both property names; different BSMT projects/targets surface different copy switches:
-p:DisableCopyToPlugins=True -p:DisableCopyToGame=True
If the purpose is to install the built artifact, copy it into plugin-helper's state downloads and use plugin-helper plan/apply, or follow docs/SMOKETEST.md for intentional live validation.
Common Reference Failures
MSB3644or missing.NETFramework,Version=v4.7.2reference assemblies: addMicrosoft.NETFramework.ReferenceAssemblies.net472.- Missing game assemblies such as
Main.dll,HMUI.dll,UnityEngine.CoreModule.dll:BeatSaberDiris wrong or incomplete. - Missing mod dependencies such as
BSML.dll,SongCore.dll,SiraUtil.dll,BeatSaberPlaylistsLib.dll: install or point at an instance containing those plugins, or fetch the dependency DLL from its verified release only when appropriate. IPA.Loader.dllmissing: BSIPA is not bootstrapped in that instance.
Artifact Handoff To plugin-helper
For a built plugin DLL intended for a managed instance:
mkdir -p .state/instances/<instance>/downloads/<plugin-id>
cp <checkout>/<path>/bin/Release/<Plugin>.dll .state/instances/<instance>/downloads/<plugin-id>/<Plugin>.dll
sha256sum .state/instances/<instance>/downloads/<plugin-id>/<Plugin>.dll
Then update registry/lock data only if the user asked to manage/install the artifact, and use:
PYTHONPATH=src python -m plugin_helper --state-dir .state check --instance <instance>
PYTHONPATH=src python -m plugin_helper --state-dir .state plan --instance <instance> --plugin <plugin-id>
PYTHONPATH=src python -m plugin_helper --state-dir .state apply <plan-path>
Inspect the generated plan before applying.