mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-03-26 04:27:28 +08:00
build: remove legacy UpdateGameDlls target and simplify PS1 script
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -18,6 +18,3 @@ build/
|
|||||||
/*/package/*.zip
|
/*/package/*.zip
|
||||||
/*/package/patchers/
|
/*/package/patchers/
|
||||||
/*/package/plugins/
|
/*/package/plugins/
|
||||||
|
|
||||||
# UpdateGameDlls build-time lock file (created by UpdateGameDlls.ps1)
|
|
||||||
AssemblyFromGame/.update.lock
|
|
||||||
|
|||||||
22
AGENTS.md
22
AGENTS.md
@@ -41,6 +41,7 @@ DSP_Mods/
|
|||||||
├── PoolOpt/ # Memory pool optimization on save loading
|
├── PoolOpt/ # Memory pool optimization on save loading
|
||||||
├── UniverseGenTweaks/ # Universe generator parameter tweaks
|
├── UniverseGenTweaks/ # Universe generator parameter tweaks
|
||||||
├── UserCloak/ # Hides/fakes Steam account info
|
├── UserCloak/ # Hides/fakes Steam account info
|
||||||
|
├── UpdateGameDlls/ # MSBuild helper project; runs UpdateGameDlls.ps1 before any mod compiles
|
||||||
└── CompressSave/ # Stub only (moved to external repo)
|
└── CompressSave/ # Stub only (moved to external repo)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -70,35 +71,34 @@ DSP_Mods/
|
|||||||
|
|
||||||
Common properties and references are factored into two root-level files that MSBuild automatically imports for every project:
|
Common properties and references are factored into two root-level files that MSBuild automatically imports for every project:
|
||||||
|
|
||||||
- **`Directory.Build.props`** — shared `PropertyGroup` defaults (`TargetFramework`, `AllowUnsafeBlocks`, `LangVersion`, `RestoreAdditionalProjectSources`) and shared `ItemGroup`s (BepInEx packages, game DLL references, `Microsoft.NETFramework.ReferenceAssemblies`).
|
- **`Directory.Build.props`** — shared `PropertyGroup` defaults (`TargetFramework`, `AllowUnsafeBlocks`, `LangVersion`, `RestoreAdditionalProjectSources`) and shared `ItemGroup`s (BepInEx packages, game DLL references, `Microsoft.NETFramework.ReferenceAssemblies`), and a global `ProjectReference` to the `UpdateGameDlls` helper project (ensuring game DLLs are refreshed before any mod project resolves assembly references).
|
||||||
- **`Directory.Build.targets`** — defines the `UpdateGameDlls`, `ZipMod`, and `CopyToParentPackage` targets (see below).
|
- **`Directory.Build.targets`** — defines the `ZipMod` and `CopyToParentPackage` targets (see below).
|
||||||
- **`UpdateGameDlls.ps1`** — PowerShell script invoked by the `UpdateGameDlls` target; locates the DSP installation via Steam registry and `libraryfolders.vdf`, compares DLL timestamps, and re-publicizes stale DLLs using `assembly-publicizer`.
|
- **`UpdateGameDlls.ps1`** — PowerShell script invoked by the `UpdateGameDlls` helper project; locates the DSP installation via Steam registry and `libraryfolders.vdf`, compares DLL timestamps, and re-publicizes stale DLLs using `assembly-publicizer`.
|
||||||
|
|
||||||
Individual `.csproj` files only declare what is unique to that project (GUID, version, extra packages, embedded resources).
|
Individual `.csproj` files only declare what is unique to that project (GUID, version, extra packages, embedded resources).
|
||||||
|
|
||||||
### Automatic Game DLL Update
|
### Automatic Game DLL Update
|
||||||
|
|
||||||
`AssemblyFromGame/` holds publicized copies of two game DLLs used as compile-time references. They are refreshed automatically **once per solution build** by the `UpdateGameDlls` MSBuild target, which calls `UpdateGameDlls.ps1`.
|
`AssemblyFromGame/` holds publicized copies of two game DLLs used as compile-time references. They are refreshed automatically before any mod project compiles by the `UpdateGameDlls` helper project.
|
||||||
|
|
||||||
The target runs only when the `UXAssist` project is being built (the designated trigger project), or when either DLL is missing from `AssemblyFromGame/`. This prevents redundant executions and file-write conflicts when projects are built in parallel (`dotnet build -m`). The PowerShell script additionally acquires an exclusive file lock (`AssemblyFromGame/.update.lock`) so that the rare case where the `!Exists` fallback triggers multiple projects concurrently is also handled safely.
|
The helper project (`UpdateGameDlls/UpdateGameDlls.csproj`) uses the `Microsoft.Build.NoTargets` SDK and is declared as a global `ProjectReference` in `Directory.Build.props` with `ReferenceOutputAssembly=false`, `SkipGetTargetFrameworkProperties=true`, and `Private=false`. This ensures that MSBuild's dependency graph guarantees the helper project completes before any mod project resolves assembly references, with no need for file locks or conditional triggers.
|
||||||
|
|
||||||
The script:
|
The `UpdateGameDlls.ps1` script:
|
||||||
1. Reads the Steam installation path from the Windows registry (`HKCU\Software\Valve\Steam`).
|
1. Reads the Steam installation path from the Windows registry (`HKCU\Software\Valve\Steam`).
|
||||||
2. Parses `steamapps/libraryfolders.vdf` to find the library that contains DSP (AppID `1366540`).
|
2. Parses `steamapps/libraryfolders.vdf` to find the library that contains DSP (AppID `1366540`).
|
||||||
3. Locates `<game_root>/DSPGAME_Data/Managed/`.
|
3. Locates `<game_root>/DSPGAME_Data/Managed/`.
|
||||||
4. Acquires an exclusive file lock on `AssemblyFromGame/.update.lock` (waits up to 60 s).
|
4. For each DLL (`Assembly-CSharp.dll`, `UnityEngine.UI.dll`): if the game copy is newer than the local copy, runs `assembly-publicizer … --strip --overwrite` to regenerate the local file and stamps it with the source timestamp.
|
||||||
5. For each DLL (`Assembly-CSharp.dll`, `UnityEngine.UI.dll`): if the game copy is newer than the local copy, runs `assembly-publicizer … --strip --overwrite` to regenerate the local file and stamps it with the source timestamp.
|
|
||||||
|
|
||||||
The target can also be run explicitly:
|
To explicitly update game DLLs:
|
||||||
```
|
```
|
||||||
dotnet build -t:UpdateGameDlls
|
dotnet build UpdateGameDlls\UpdateGameDlls.csproj
|
||||||
```
|
```
|
||||||
|
|
||||||
**Prerequisite:** `assembly-publicizer` must be installed as a .NET global tool:
|
**Prerequisite:** `assembly-publicizer` must be installed as a .NET global tool:
|
||||||
```
|
```
|
||||||
dotnet tool install -g BepInEx.AssemblyPublicizer.Cli
|
dotnet tool install -g BepInEx.AssemblyPublicizer.Cli
|
||||||
```
|
```
|
||||||
If the tool is missing or DSP is not found, the target prints a warning and continues without failing the build.
|
If the tool is missing or DSP is not found, the script prints a warning and continues without failing the build.
|
||||||
|
|
||||||
### Packaging
|
### Packaging
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project>
|
<Project>
|
||||||
<!--
|
|
||||||
UpdateGameDlls target: locates the Dyson Sphere Program installation via the
|
|
||||||
Steam registry and libraryfolders.vdf, then uses assembly-publicizer to
|
|
||||||
refresh AssemblyFromGame/ whenever the game DLLs are newer than the local copies.
|
|
||||||
|
|
||||||
Runs automatically before every build (BeforeTargets="BeforeBuild") and can
|
|
||||||
also be invoked explicitly:
|
|
||||||
dotnet build -t:UpdateGameDlls
|
|
||||||
|
|
||||||
Requires assembly-publicizer on PATH or in %USERPROFILE%\.dotnet\tools\:
|
|
||||||
dotnet tool install -g BepInEx.AssemblyPublicizer.Cli
|
|
||||||
-->
|
|
||||||
<!--
|
|
||||||
The target is conditioned to run only when building the 'UXAssist' project (the
|
|
||||||
designated first-built project in this solution), OR when either game DLL is
|
|
||||||
missing entirely (e.g. after a manual deletion). This ensures the target fires
|
|
||||||
exactly once per solution build even when projects are built in parallel (-m),
|
|
||||||
while still recovering automatically if the DLLs are absent.
|
|
||||||
|
|
||||||
The PowerShell script additionally acquires an exclusive file lock on
|
|
||||||
AssemblyFromGame/.update.lock so that the rare case where the !Exists fallback
|
|
||||||
triggers multiple projects concurrently is also handled safely.
|
|
||||||
-->
|
|
||||||
<Target Name="UpdateGameDlls" BeforeTargets="BeforeBuild"
|
|
||||||
Condition="'$(MSBuildProjectName)' == 'UXAssist'
|
|
||||||
Or !Exists('$(MSBuildThisFileDirectory)AssemblyFromGame\Assembly-CSharp.dll')
|
|
||||||
Or !Exists('$(MSBuildThisFileDirectory)AssemblyFromGame\UnityEngine.UI.dll')"
|
|
||||||
>
|
|
||||||
<Exec
|
|
||||||
Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$(MSBuildThisFileDirectory)UpdateGameDlls.ps1" -ProjectRoot "$(MSBuildThisFileDirectory.TrimEnd('\\/'))""
|
|
||||||
ConsoleToMSBuild="true"
|
|
||||||
IgnoreExitCode="false"
|
|
||||||
WorkingDirectory="$(MSBuildThisFileDirectory)" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
ZipMod target: assembles a Thunderstore-ready zip under package/.
|
ZipMod target: assembles a Thunderstore-ready zip under package/.
|
||||||
|
|||||||
@@ -130,34 +130,7 @@ if (-not $publicizer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# 5. Acquire an exclusive file lock so that concurrent MSBuild nodes (triggered
|
# 5. For each DLL: compare timestamps, publicize if game copy is newer
|
||||||
# by the !Exists fallback condition) cannot write the DLLs simultaneously.
|
|
||||||
# The lock is released automatically in the finally block.
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
$lockPath = Join-Path $OUTPUT_DIR '.update.lock'
|
|
||||||
$lockStream = $null
|
|
||||||
try {
|
|
||||||
# Retry loop: wait up to 60 s for the lock (another node may be updating)
|
|
||||||
$deadline = [DateTime]::UtcNow.AddSeconds(60)
|
|
||||||
while ($true) {
|
|
||||||
try {
|
|
||||||
$lockStream = [System.IO.File]::Open(
|
|
||||||
$lockPath,
|
|
||||||
[System.IO.FileMode]::OpenOrCreate,
|
|
||||||
[System.IO.FileAccess]::ReadWrite,
|
|
||||||
[System.IO.FileShare]::None)
|
|
||||||
break # lock acquired
|
|
||||||
} catch [System.IO.IOException] {
|
|
||||||
if ([DateTime]::UtcNow -ge $deadline) {
|
|
||||||
Write-Warning 'UpdateGameDlls: Timed out waiting for lock; skipping DLL update.'
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
Start-Sleep -Milliseconds 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# 6. For each DLL: compare timestamps, publicize if game copy is newer
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
$updated = 0
|
$updated = 0
|
||||||
foreach ($dll in $DSP_DLLS) {
|
foreach ($dll in $DSP_DLLS) {
|
||||||
@@ -203,8 +176,3 @@ if ($updated -gt 0) {
|
|||||||
} else {
|
} else {
|
||||||
Write-Host 'UpdateGameDlls: All DLLs are up-to-date.'
|
Write-Host 'UpdateGameDlls: All DLLs are up-to-date.'
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
|
||||||
# Release the exclusive lock regardless of success or failure
|
|
||||||
if ($lockStream) { $lockStream.Close() }
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user