Skip to content

Commit 089d006

Browse files
authored
Merge pull request #1113 from JMartinezRuiz/codex/fix-visionos-buildtarget
fix(build): avoid compile-time VisionOS enum references
2 parents 7abd6e3 + 75c844f commit 089d006

4 files changed

Lines changed: 147 additions & 14 deletions

File tree

MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
using System;
12
using UnityEditor;
23
using UnityEditor.Build;
34

45
namespace MCPForUnity.Editor.Tools.Build
56
{
67
public static class BuildTargetMapping
78
{
9+
private const string VisionOSName = "VisionOS";
10+
811
public static bool TryResolveBuildTarget(string name, out BuildTarget target)
912
{
1013
if (string.IsNullOrEmpty(name))
@@ -24,13 +27,12 @@ public static bool TryResolveBuildTarget(string name, out BuildTarget target)
2427
case "webgl": target = BuildTarget.WebGL; return true;
2528
case "uwp": target = BuildTarget.WSAPlayer; return true;
2629
case "tvos": target = BuildTarget.tvOS; return true;
27-
// BuildTarget.VisionOS exists only in Unity 2023.2+ and late 2022.3 patches
28-
#if UNITY_2023_2_OR_NEWER
29-
case "visionos": target = BuildTarget.VisionOS; return true;
30-
#endif
3130
default:
32-
if (System.Enum.TryParse(name, true, out target))
31+
if (TryParseDefinedBuildTarget(name, out target))
32+
{
3333
return true;
34+
}
35+
3436
target = default;
3537
return false;
3638
}
@@ -50,10 +52,14 @@ public static BuildTargetGroup GetTargetGroup(BuildTarget target)
5052
case BuildTarget.WebGL: return BuildTargetGroup.WebGL;
5153
case BuildTarget.WSAPlayer: return BuildTargetGroup.WSA;
5254
case BuildTarget.tvOS: return BuildTargetGroup.tvOS;
53-
#if UNITY_2023_2_OR_NEWER
54-
case BuildTarget.VisionOS: return BuildTargetGroup.VisionOS;
55-
#endif
56-
default: return BuildTargetGroup.Unknown;
55+
default:
56+
if (IsVisionOSTarget(target)
57+
&& Enum.TryParse(VisionOSName, true, out BuildTargetGroup visionOSGroup))
58+
{
59+
return visionOSGroup;
60+
}
61+
62+
return BuildTargetGroup.Unknown;
5763
}
5864
}
5965

@@ -67,12 +73,61 @@ public static string TryResolveNamedBuildTarget(string name, out NamedBuildTarge
6773
if (!TryResolveBuildTarget(name, out var buildTarget))
6874
{
6975
namedTarget = default;
70-
return $"Unknown build target: '{name}'. Valid targets: windows64, osx, linux64, android, ios, webgl, uwp, tvos, visionos";
76+
return GetUnknownBuildTargetMessage(name);
77+
}
78+
79+
var targetGroup = GetTargetGroup(buildTarget);
80+
if (targetGroup == BuildTargetGroup.Unknown)
81+
{
82+
namedTarget = default;
83+
return IsVisionOSTarget(buildTarget)
84+
? "VisionOS build target is available, but its BuildTargetGroup is not exposed by this Unity editor installation."
85+
: $"Build target group could not be resolved for target '{buildTarget}'.";
7186
}
72-
namedTarget = GetNamedBuildTarget(buildTarget);
87+
88+
namedTarget = NamedBuildTarget.FromBuildTargetGroup(targetGroup);
7389
return null;
7490
}
7591

92+
public static string GetUnknownBuildTargetMessage(string name)
93+
{
94+
if (string.Equals(name, "visionos", StringComparison.OrdinalIgnoreCase))
95+
{
96+
return "VisionOS build target is not available in this Unity editor installation. "
97+
+ "Install the visionOS build support module or use a Unity version/configuration that exposes BuildTarget.VisionOS.";
98+
}
99+
100+
return $"Unknown build target: '{name}'. Valid targets: {GetValidTargetsList()}.";
101+
}
102+
103+
private static string GetValidTargetsList()
104+
{
105+
string validTargets = "windows64, osx, linux64, android, ios, webgl, uwp, tvos";
106+
if (TryParseDefinedBuildTarget(VisionOSName, out _))
107+
{
108+
validTargets += ", visionos";
109+
}
110+
111+
return validTargets;
112+
}
113+
114+
private static bool IsVisionOSTarget(BuildTarget target)
115+
{
116+
return string.Equals(target.ToString(), VisionOSName, StringComparison.OrdinalIgnoreCase);
117+
}
118+
119+
private static bool TryParseDefinedBuildTarget(string name, out BuildTarget target)
120+
{
121+
target = default;
122+
if (int.TryParse(name, out _))
123+
{
124+
return false;
125+
}
126+
127+
return Enum.TryParse(name, true, out target)
128+
&& Enum.IsDefined(typeof(BuildTarget), target);
129+
}
130+
76131
public static string GetDefaultOutputPath(BuildTarget target, string productName)
77132
{
78133
string basePath = $"Builds/{target}";

MCPForUnity/Editor/Tools/ManageBuild.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ private static object HandleBuild(ToolParams p)
6464

6565
string targetName = p.Get("target");
6666
if (!BuildTargetMapping.TryResolveBuildTarget(targetName, out var target))
67-
return new ErrorResponse($"Unknown target '{targetName}'.");
67+
return new ErrorResponse(BuildTargetMapping.GetUnknownBuildTargetMessage(targetName));
6868

6969
var group = BuildTargetMapping.GetTargetGroup(target);
7070
if (!BuildPipeline.IsBuildTargetSupported(group, target))
@@ -221,7 +221,7 @@ private static object HandlePlatform(ToolParams p)
221221

222222
// Switch platform
223223
if (!BuildTargetMapping.TryResolveBuildTarget(targetName, out var target))
224-
return new ErrorResponse($"Unknown target '{targetName}'.");
224+
return new ErrorResponse(BuildTargetMapping.GetUnknownBuildTargetMessage(targetName));
225225

226226
var group = BuildTargetMapping.GetTargetGroup(target);
227227
if (!BuildPipeline.IsBuildTargetSupported(group, target))
@@ -442,7 +442,7 @@ private static object HandleBatch(ToolParams p)
442442
foreach (var t in targets)
443443
{
444444
if (!BuildTargetMapping.TryResolveBuildTarget(t, out var bt))
445-
return new ErrorResponse($"Unknown target '{t}' in batch.");
445+
return new ErrorResponse(BuildTargetMapping.GetUnknownBuildTargetMessage(t));
446446
var btGroup = BuildTargetMapping.GetTargetGroup(bt);
447447
if (!BuildPipeline.IsBuildTargetSupported(btGroup, bt))
448448
return new ErrorResponse(
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using MCPForUnity.Editor.Tools.Build;
3+
using NUnit.Framework;
4+
using UnityEditor;
5+
6+
namespace MCPForUnity.Tests.EditMode.Tools
7+
{
8+
[TestFixture]
9+
public class BuildTargetMappingTests
10+
{
11+
[TestCase("windows64", BuildTarget.StandaloneWindows64)]
12+
[TestCase("macos", BuildTarget.StandaloneOSX)]
13+
[TestCase("linux", BuildTarget.StandaloneLinux64)]
14+
[TestCase("tvos", BuildTarget.tvOS)]
15+
public void TryResolveBuildTarget_KnownAliasesResolve(string name, BuildTarget expected)
16+
{
17+
Assert.IsTrue(BuildTargetMapping.TryResolveBuildTarget(name, out var target));
18+
Assert.AreEqual(expected, target);
19+
}
20+
21+
[Test]
22+
public void TryResolveBuildTarget_NumericInputDoesNotResolve()
23+
{
24+
Assert.IsFalse(BuildTargetMapping.TryResolveBuildTarget("5", out _));
25+
}
26+
27+
[Test]
28+
public void TryResolveNamedBuildTarget_UnknownTargetListsOnlyAvailableTargets()
29+
{
30+
string error = BuildTargetMapping.TryResolveNamedBuildTarget("not-a-target", out _);
31+
32+
Assert.IsNotNull(error);
33+
StringAssert.Contains("windows64", error);
34+
35+
bool visionOSAvailable = Enum.TryParse("VisionOS", true, out BuildTarget _);
36+
if (visionOSAvailable)
37+
{
38+
StringAssert.Contains("visionos", error);
39+
}
40+
else
41+
{
42+
Assert.IsFalse(error.Contains("visionos"));
43+
}
44+
}
45+
46+
[Test]
47+
public void TryResolveNamedBuildTarget_VisionOSUnavailableReturnsHelpfulError()
48+
{
49+
bool visionOSAvailable = Enum.TryParse("VisionOS", true, out BuildTarget _);
50+
string error = BuildTargetMapping.TryResolveNamedBuildTarget("visionos", out _);
51+
52+
if (visionOSAvailable)
53+
{
54+
Assert.IsTrue(BuildTargetMapping.TryResolveBuildTarget("visionos", out _));
55+
Assert.IsTrue(
56+
error == null || error.Contains("VisionOS"),
57+
$"Expected no error or a VisionOS-specific error, got: {error}");
58+
}
59+
else
60+
{
61+
Assert.IsFalse(BuildTargetMapping.TryResolveBuildTarget("visionos", out _));
62+
Assert.IsNotNull(error);
63+
StringAssert.Contains("VisionOS build target is not available", error);
64+
}
65+
}
66+
}
67+
}

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)