fix(windows): run Windows post-build steps when cross-compiling from a macOS/Linux editor - #209
Open
bobbyg603 wants to merge 1 commit into
Open
fix(windows): run Windows post-build steps when cross-compiling from a macOS/Linux editor#209bobbyg603 wants to merge 1 commit into
bobbyg603 wants to merge 1 commit into
Conversation
The Windows post-build branch was selected by `#elif UNITY_EDITOR_WIN`, an editor-OS define, in a chain whose other arms (`UNITY_IOS`, `UNITY_ANDROID`) are build-target defines. Building a Windows player from a macOS or Linux editor therefore compiled the entire Windows region out: no BugSplatMonitor.exe /BugSplatRc.dll/BugSplatWer.dll next to the player, no LineNumberMappings.json zipped, no symbol upload, and no warning. The build looked clean and native crash reporting was inert at runtime. Nothing in the support-file copy needs a Windows editor -- it reads the PE machine field off the built executable and copies files out of the package's Support~ directory, all plain System.IO. Gate it on the BuildTarget the callback is already handed, matching how the macOS branch has always worked. `UnityEditor.WindowsStandalone.UserBuildSettings.copyPDBFiles` does need a Windows editor, so it keeps its `UNITY_EDITOR_WIN` guard, narrowed to the check itself. Cross-compiling now warns that the setting could not be read instead of silently doing nothing. The set of translation units that reference `UnityEditor.WindowsStandalone` is unchanged, so no new platform-module reference is introduced on any editor OS. Closes #151 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes Windows post-build processing when building a Windows player from a macOS/Linux Unity editor by keying the dispatch on BuildTarget (Windows) instead of UNITY_EDITOR_WIN (host editor OS), while keeping the one Windows-editor-only API call guarded.
Changes:
- Ends the
#if UNITY_IOS / #elif UNITY_ANDROIDchain before the Windows branch so Windows post-build steps run forBuildTarget.StandaloneWindows*regardless of editor OS. - Removes the file-level
#if UNITY_EDITOR_WINwrapper around Windows helper methods so they remain compiled for cross-compiles. - Narrows the
UNITY_EDITOR_WINguard to only theUserBuildSettings.copyPDBFilescheck and adds a warning on non-Windows editors when the setting can’t be read.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
daveplunkett
approved these changes
Aug 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #151
What was broken
OnPostprocessBuilddispatched to the Windows post-build work from a preprocessor chain that mixes two unrelated axes:UNITY_EDITOR_WINdescribes the machine running the editor, not the platform being built. All ofPostProcessWindows,UploadSymbolFilesWin,CopyWindowsLineNumberMappingsandGetPEMachineArchitecturealso lived inside a file-level#if UNITY_EDITOR_WINregion.So building a Windows player from a macOS or Linux editor compiled every one of those methods out of the assembly. The result:
BugSplatMonitor.exe/BugSplatRc.dll/BugSplatWer.dllcopied next to the player, soUseNativeCrashReportingForWindowsproduced a build with no out-of-process monitor and no WER helperLineNumberMappings.json.zip, so no IL2CPP C# symbolicationThis is verified, not assumed. See the compile evidence below.
What changed
One file,
Editor/PostBuild.cs, +6/-4.#if UNITY_IOS / #elif UNITY_ANDROIDchain is closed with#endifbefore the Windows block, and the Windows block is now dispatched unconditionally ontarget == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows— exactly the shape the macOS branch on the next line has always had.#if UNITY_EDITOR_WINregion around the Windows helpers is removed. Nothing in it needs a Windows editor: it reads the COFF machine field off the built.exeand copies files out of the package'sRuntime/Plugins/Windows/Support~/<arch>directory, all plainSystem.IOplusUnityEditor.PackageManager.PackageInfoand theBuildTargetenum, which are coreUnityEditor.dll.UnityEditor.WindowsStandalone.UserBuildSettings.copyPDBFiles, keeps itsUNITY_EDITOR_WINguard — narrowed from the whole region down to the check itself. The#elsearm warns that the setting could not be read and that symbolication will fail if it happens to be off, then proceeds with the upload rather than silently skipping it.Deliberately unchanged: the
using UnityEditor.WindowsStandalone;at the top stays under#if UNITY_EDITOR_WIN. The set of translation units that reference theUnityEditor.WindowsStandaloneplatform module is therefore bit-for-bit identical to before — the reference is compiled iffUNITY_EDITOR_WIN, on every build target, exactly as it was. No new platform-module reference is introduced on any editor OS, which is what makes this safe to do without touching the iOS/Android guards.#ifpermutation analysisEditor OS x active build target.
UNITY_STANDALONE_WINetc. are the target defines;UNITY_EDITOR_*the host defines.#elif UNITY_EDITOR_WINtrue -> block compiled and runs;copyPDBFileschecked#if UNITY_EDITOR_WINtrue socopyPDBFilesstill checked. No behavior changeUNITY_IOSfalse,UNITY_ANDROIDfalse,UNITY_EDITOR_WINfalse -> nothing compiled, silent no-opcopyPDBFilescould not be read#if UNITY_IOSwins; Windows helpers still compiled by the file-levelUNITY_EDITOR_WINregiontarget == StandaloneWindows*is false -> no-op. Same reference set as before#elsearm is taken, so noUnityEditor.WindowsStandalonereference; dispatch is a no-op#elif UNITY_ANDROIDwins; helpers compiled by the file-level region#elsearm, dispatch no-opPostProcessMacrunsTwo things this table makes explicit:
One incidental robustness gain: because the Windows block now sits after
#endifrather than inside the#elifchain, a build where the target defines disagree with thetargetargument (batch-mode-buildTargetbefore a script recompile) still runs the Windows steps instead of falling through the chain into nothing.What I verified
I cannot run Unity, so there is no real player build behind this. What I did instead was compile the package's
Editor/andRuntime/sources withdotnet buildagainst Unity 6000.5.6f1'sUnityEditor.dll/UnityEngine.dll, plus the real platform-module assemblies fromEditor/Data/PlaybackEngines/, toggling the defines and the module references per permutation.Compiled clean (0 errors) in all of:
UnityEditor.WindowsStandalone.ExtensionsreferencedUNITY_EDITOR_WIN+UNITY_STANDALONE_WINUNITY_EDITOR_OSX+UNITY_STANDALONE_WINUNITY_EDITOR_LINUX+UNITY_STANDALONE_WINUNITY_EDITOR_OSX+UNITY_STANDALONE_OSXUNITY_EDITOR_WIN+UNITY_ANDROID(+ Android extensions)UNITY_EDITOR_OSX+UNITY_ANDROID(+ Android extensions)Negative control, to prove the harness actually has teeth rather than silently resolving the module anyway: compiling with
UNITY_EDITOR_WINdefined but theUnityEditor.WindowsStandalone.Extensionsreference removed fails withCS0234: The type or namespace name 'WindowsStandalone' does not exist in the namespace 'UnityEditor'. So the non-Windows rows above passing is meaningful — the#elsearm genuinely avoids the platform-module dependency.Bug reproduced against the compiled output. I built the pre-fix and post-fix sources under
UNITY_EDITOR_OSX + UNITY_STANDALONE_WINand inspected the emitted assembly's metadata for the method names:PostProcessWindows— absent.GetPEMachineArchitecture— absent.That is direct confirmation the whole Windows post-build path was being compiled away when cross-compiling, and that it now survives.
What I could NOT verify
Stating these plainly rather than implying broader coverage:
BugSplatMonitor.exe/BugSplatWer.dllactually catch a crash in a Mac-cross-compiled Windows player. It proves the code that copies them now compiles and is reachable.UNITY_IOSpermutations were not compiled. The iOS build module is not installed on this machine, soUnityEditor.iOS.Xcodecannot resolve and rows 4/5 of the compile table are reasoned-through only, not built. I consider the risk low because the change does not touch the#if UNITY_IOSarm and adds no reference the iOS-target compilation did not already have on a Windows editor, but it is unverified.UnityEditor.WindowsStandalone.Extensionson a macOS/Linux editor is not settled — and deliberately does not need to be. I kept theUNITY_EDITOR_WINguard on that one API precisely so the answer does not matter. If it turns out the module is referenced cross-platform, thecopyPDBFilescheck could later be widened and the warning dropped; that would be a follow-up, not a prerequisite.#elsewarning fires on every cross-compiled Windows build, including ones where "Copy PDB files" is in fact enabled and everything works. That is intentional — the setting is unreadable from the host, so the honest message is "not checked" — but it is noise, and worth revisiting if it annoys people.symbol-uploadvariant selection still keys onApplication.platform, so an Intel Mac editor getssymbol-upload-macosrather thansymbol-upload-macos-intel. Pre-existing, out of scope here, adjacent to G1: Symbol upload silently fails for registry and git package installs #150.Merge-conflict surface
Scoped to only the Windows platform gating, to stay clear of the two other in-flight PRs against this file:
UploadSymbolFilesWin's guard)#endifat the old end of the Windows regionUploadSymbols/DownloadSymbolUpload(#150) and the Android upload callback (#162) are untouched.🤖 Generated with Claude Code