ProjectDDD/Packages/com.singularitygroup.hotreload/Editor/Helpers/BuildInfoHelper.cs
2025-07-08 19:46:31 +09:00

144 lines
6.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
namespace SingularityGroup.HotReload.Editor {
struct BuildInfoInput {
public readonly string allDefineSymbols;
public readonly BuildTarget activeBuildTarget;
public readonly string[] omittedProjects;
public readonly bool batchMode;
public BuildInfoInput(string allDefineSymbols, BuildTarget activeBuildTarget, string[] omittedProjects, bool batchMode) {
this.allDefineSymbols = allDefineSymbols;
this.activeBuildTarget = activeBuildTarget;
this.omittedProjects = omittedProjects;
this.batchMode = batchMode;
}
}
static class BuildInfoHelper {
public static async Task<BuildInfoInput> GetGenerateBuildInfoInput() {
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
var activeDefineSymbols = EditorUserBuildSettings.activeScriptCompilationDefines;
var batchMode = Application.isBatchMode;
var allDefineSymbols = await Task.Run(() => {
return GetAllAndroidMonoBuildDefineSymbolsThreaded(activeDefineSymbols);
});
// cached so unexpensive most of the time
var omittedProjects = AssemblyOmission.GetOmittedProjects(allDefineSymbols);
return new BuildInfoInput(
allDefineSymbols: allDefineSymbols,
activeBuildTarget: buildTarget,
omittedProjects: omittedProjects,
batchMode: batchMode
);
}
public static BuildInfo GenerateBuildInfoMainThread() {
return GenerateBuildInfoMainThread(EditorUserBuildSettings.activeBuildTarget);
}
public static BuildInfo GenerateBuildInfoMainThread(BuildTarget buildTarget) {
var allDefineSymbols = GetAllAndroidMonoBuildDefineSymbolsThreaded(EditorUserBuildSettings.activeScriptCompilationDefines);
return GenerateBuildInfoThreaded(new BuildInfoInput(
allDefineSymbols: allDefineSymbols,
activeBuildTarget: buildTarget,
omittedProjects: AssemblyOmission.GetOmittedProjects(allDefineSymbols),
batchMode: Application.isBatchMode
));
}
public static BuildInfo GenerateBuildInfoThreaded(BuildInfoInput input) {
var omittedProjectRegex = String.Join("|", input.omittedProjects.Select(name => Regex.Escape(name)));
var shortCommitHash = GitUtil.GetShortCommitHashOrFallback();
var hostname = IsHumanControllingUs(input.batchMode) ? IpHelper.GetIpAddress() : null;
// Note: add a string to uniquely identify the Unity project. Could use filepath to /MyProject/Assets/ (editor Application.dataPath)
// or application identifier (com.company.appname).
// Do this when supporting multiple projects: SG-28807
// The matching code is in Runtime assembly which compares server response with built BuildInfo.
return new BuildInfo {
projectIdentifier = "SG-29580",
commitHash = shortCommitHash,
defineSymbols = input.allDefineSymbols,
projectOmissionRegex = omittedProjectRegex,
buildMachineHostName = hostname,
buildMachinePort = RequestHelper.port,
activeBuildTarget = input.activeBuildTarget.ToString(),
buildMachineRequestOrigin = RequestHelper.origin,
};
}
public static bool IsHumanControllingUs(bool batchMode) {
if (batchMode) {
return false;
}
var isCI = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI"));
return !isCI;
}
private static readonly string[] editorSymbolsToRemove = {
"PLATFORM_ARCH_64",
"UNITY_64",
"UNITY_INCLUDE_TESTS",
"UNITY_EDITOR",
"UNITY_EDITOR_64",
"UNITY_EDITOR_WIN",
"ENABLE_UNITY_COLLECTIONS_CHECKS",
"ENABLE_BURST_AOT",
"RENDER_SOFTWARE_CURSOR",
"PLATFORM_STANDALONE_WIN",
"PLATFORM_STANDALONE",
"UNITY_STANDALONE_WIN",
"UNITY_STANDALONE",
"ENABLE_MOVIES",
"ENABLE_OUT_OF_PROCESS_CRASH_HANDLER",
"ENABLE_WEBSOCKET_HOST",
"ENABLE_CLUSTER_SYNC",
"ENABLE_CLUSTERINPUT",
};
private static readonly string[] androidSymbolsToAdd = {
"CSHARP_7_OR_LATER",
"CSHARP_7_3_OR_NEWER",
"PLATFORM_ANDROID",
"UNITY_ANDROID",
"UNITY_ANDROID_API",
"ENABLE_EGL",
"DEVELOPMENT_BUILD",
"ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING",
"PLATFORM_SUPPORTS_ADS_ID",
"UNITY_CAN_SHOW_SPLASH_SCREEN",
"UNITY_HAS_GOOGLEVR",
"UNITY_HAS_TANGO",
"ENABLE_SPATIALTRACKING",
"ENABLE_RUNTIME_PERMISSIONS",
"ENABLE_ENGINE_CODE_STRIPPING",
"UNITY_ASTC_ONLY_DECOMPRESS",
"ANDROID_USE_SWAPPY",
"ENABLE_ONSCREEN_KEYBOARD",
"ENABLE_UNITYADS_RUNTIME",
"UNITY_UNITYADS_API",
};
// Currently there is no better way. Alternatively we could hook into unity's call to csc.exe and parse the /define: arguments.
// Hardcoding the differences was less effort and is less error prone.
// I also looked into it and tried all the Build interfaces like this one https://docs.unity3d.com/ScriptReference/Build.IPostBuildPlayerScriptDLLs.html
// and logging EditorUserBuildSettings.activeScriptCompilationDefines in the callbacks - result: all same like editor, so I agree that hardcode is best.
public static string GetAllAndroidMonoBuildDefineSymbolsThreaded(string[] defineSymbols) {
var defines = new HashSet<string>(defineSymbols);
defines.ExceptWith(editorSymbolsToRemove);
defines.UnionWith(androidSymbolsToAdd);
// sort for consistency, must be deterministic
var definesArray = defines.OrderBy(def => def).ToArray();
return String.Join(";", definesArray);
}
}
}