diff --git a/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildTools.cs b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildTools.cs index 3f26fbc..845935a 100644 --- a/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildTools.cs +++ b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildTools.cs @@ -11,145 +11,68 @@ using System.IO; using UnityEditor; using UnityEditor.Build; -using UnityEngine; -using UnityEngine.Serialization; using Debug = UnityEngine.Debug; namespace Microsoft.Build.Unity.ProjectGeneration { - public class MSBuildToolsConfig - { - private const int CurrentConfigVersion = 3; - - private static string MSBuildSettingsFilePath { get; } = Path.Combine(Utilities.ProjectPath, "MSBuild", "settings.json"); - - [SerializeField] - private int version = 0; - - [FormerlySerializedAs("autoGenerateEnabled")] - [SerializeField] - private bool fullGenerationEnabled = false; - - [SerializeField] - private string dependenciesProjectGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string assemblyCSharpGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string assemblyCSharpEditorGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string assemblyCSharpFirstPassGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string assemblyCSharpFirstPassEditorGuid = Guid.NewGuid().ToString(); - [SerializeField] - private string builtInPackagesFolderGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string importedPackagesFolderGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string externalPackagesFolderGuid = Guid.NewGuid().ToString(); - - [SerializeField] - private string solutionGuid = Guid.NewGuid().ToString(); - - public bool FullGenerationEnabled - { - get => fullGenerationEnabled; - set - { - fullGenerationEnabled = value; - Save(); - } - } - - internal Guid DependenciesProjectGuid { get; private set; } - - internal Guid AssemblyCSharpGuid { get; private set; } - - internal Guid AssemblyCSharpEditorGuid { get; private set; } - - internal Guid AssemblyCSharpFirstPassGuid { get; private set; } - - internal Guid AssemblyCSharpFirstPassEditorGuid { get; private set; } - - internal Guid BuiltInPackagesFolderGuid { get; private set; } - - internal Guid ImportedPackagesFolderGuid { get; private set; } - - internal Guid ExternalPackagesFolderGuid { get; private set; } - - internal Guid SolutionGuid { get; private set; } - - private void Save() - { - // Ensure directory exists first - Directory.CreateDirectory(Path.GetDirectoryName(MSBuildSettingsFilePath)); - File.WriteAllText(MSBuildSettingsFilePath, EditorJsonUtility.ToJson(this)); - } + /// + /// Class that exposes the MSBuild project generation operation. + /// + [InitializeOnLoad] + public static class MSBuildTools + { + private static bool CSProjectAssetChanged = false; + private static bool AssemblyDefinitionAssetChanged = false; + private static bool CSProjectAssetRemoved = false; - public static MSBuildToolsConfig Load() + private class AssetPostprocessor : UnityEditor.AssetPostprocessor { - MSBuildToolsConfig toReturn = new MSBuildToolsConfig(); - - if (File.Exists(MSBuildSettingsFilePath)) + private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { - EditorJsonUtility.FromJsonOverwrite(File.ReadAllText(MSBuildSettingsFilePath), toReturn); - } - - bool needToSave = false; - - toReturn.DependenciesProjectGuid = EnsureGuid(ref toReturn.dependenciesProjectGuid, ref needToSave); - - toReturn.AssemblyCSharpGuid = EnsureGuid(ref toReturn.assemblyCSharpGuid, ref needToSave); - toReturn.AssemblyCSharpEditorGuid = EnsureGuid(ref toReturn.assemblyCSharpEditorGuid, ref needToSave); - toReturn.AssemblyCSharpFirstPassGuid = EnsureGuid(ref toReturn.assemblyCSharpFirstPassGuid, ref needToSave); - toReturn.AssemblyCSharpFirstPassEditorGuid = EnsureGuid(ref toReturn.assemblyCSharpFirstPassEditorGuid, ref needToSave); - - toReturn.BuiltInPackagesFolderGuid = EnsureGuid(ref toReturn.builtInPackagesFolderGuid, ref needToSave); - toReturn.ImportedPackagesFolderGuid = EnsureGuid(ref toReturn.importedPackagesFolderGuid, ref needToSave); - toReturn.ExternalPackagesFolderGuid = EnsureGuid(ref toReturn.externalPackagesFolderGuid, ref needToSave); + // Check for deleted path first + CheckPathsForChanges(deletedAssets); + CSProjectAssetRemoved = CSProjectAssetChanged; - toReturn.SolutionGuid = EnsureGuid(ref toReturn.solutionGuid, ref needToSave); + CheckPathsForChanges(importedAssets, movedAssets, movedFromAssetPaths); - if (CurrentConfigVersion > toReturn.version) - { - toReturn.version = CurrentConfigVersion; - needToSave = true; - } - - if (needToSave) - { - toReturn.Save(); + if (AssemblyDefinitionAssetChanged || CSProjectAssetChanged) + { + RefreshGeneratedOutput(forceGenerateEverything: false, forceCompleteGeneration: false); + } } - return toReturn; - } - - private static Guid EnsureGuid(ref string field, ref bool needToSave) - { - if (!Guid.TryParse(field, out Guid guid)) + public static void CheckPathsForChanges(params string[][] assetPathSets) { - guid = Guid.NewGuid(); - field = guid.ToString(); - - needToSave = true; + foreach (string[] assetPathSet in assetPathSets) + { + foreach (string assetPath in assetPathSet) + { + if (CSProjectAssetChanged && AssemblyDefinitionAssetChanged) + { + // Break out early since both are now true + return; + } + + string extension = Path.GetExtension(assetPath).ToLower(); + + if (extension == ".csproj") + { + // Ignore generated projects + if (!assetPath.EndsWith(".msb4u.csproj", StringComparison.CurrentCultureIgnoreCase)) + { + CSProjectAssetChanged = true; + } + } + else if (extension == ".asmdef") + { + AssemblyDefinitionAssetChanged = true; + } + } + } } - - return guid; } - } - /// - /// Class that exposes the MSBuild project generation operation. - /// - [InitializeOnLoad] - public static class MSBuildTools - { private class BuildTargetChanged : IActiveBuildTargetChanged { public int callbackOrder => 0; @@ -281,9 +204,10 @@ private static void RefreshGeneratedOutput(bool forceGenerateEverything, bool fo || EditorPrefs.GetInt($"{nameof(MSBuildTools)}.{nameof(targetFramework)}") != (int)targetFramework || forceGenerateEverything; - if (buildTargetOrFrameworkChanged) + if (buildTargetOrFrameworkChanged || CSProjectAssetRemoved) { // We clean up previous build if the EditorPrefs currentBuildTarget or targetFramework is different from current ones. + // Or a CS Project file has been removed and we need to clean up MSBuildProjectBuilder.TryBuildAllProjects(MSBuildProjectBuilder.CleanProfileName); } @@ -297,9 +221,17 @@ private static void RefreshGeneratedOutput(bool forceGenerateEverything, bool fo // - forceGenerateEverything is true (we are told to) // - buildTargetOrFrameworkChanged is true (target framework changed) // - doesCurrentVersionTokenFileExist is false (version changed, or editor just opened) + // - CSProjectAssetChanged is true (a csproj file has been added) + // - AssemblyDefinitionAssetChanged is true and Config.FullGenerationEnabled is true (asmdef change and full regen is enabled that will gen based off asmdefs) // - AutoGenerateEnabled and token file doesn't exist or shouldClean is true - bool performRegeneration = forceGenerateEverything || buildTargetOrFrameworkChanged || !doesCurrentVersionTokenFileExist; + bool performRegeneration = forceGenerateEverything || buildTargetOrFrameworkChanged || !doesCurrentVersionTokenFileExist || CSProjectAssetChanged + || (AssemblyDefinitionAssetChanged && Config.FullGenerationEnabled); + + // Reset the values after using them + CSProjectAssetChanged = false; + AssemblyDefinitionAssetChanged = false; + CSProjectAssetRemoved = false; if (performRegeneration || unityProjectInfo == null) { @@ -328,8 +260,8 @@ private static void RefreshGeneratedOutput(bool forceGenerateEverything, bool fo EditorPrefs.SetInt($"{nameof(MSBuildTools)}.{nameof(currentBuildTarget)}", (int)currentBuildTarget); EditorPrefs.SetInt($"{nameof(MSBuildTools)}.{nameof(targetFramework)}", (int)targetFramework); - // If we cleaned, now build - if (buildTargetOrFrameworkChanged) + // If we cleaned, now build, or if we regenerated + if (buildTargetOrFrameworkChanged || performRegeneration) { MSBuildProjectBuilder.TryBuildAllProjects(MSBuildProjectBuilder.BuildProfileName); } diff --git a/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs new file mode 100644 index 0000000..13dc61e --- /dev/null +++ b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#if UNITY_EDITOR +using System; +using System.IO; +using UnityEditor; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Microsoft.Build.Unity.ProjectGeneration +{ + public class MSBuildToolsConfig + { + private const int CurrentConfigVersion = 3; + + private static string MSBuildSettingsFilePath { get; } = Path.Combine(Utilities.ProjectPath, "MSBuild", "settings.json"); + + [SerializeField] + private int version = 0; + + [FormerlySerializedAs("autoGenerateEnabled")] + [SerializeField] + private bool fullGenerationEnabled = false; + + [SerializeField] + private string dependenciesProjectGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string assemblyCSharpGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string assemblyCSharpEditorGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string assemblyCSharpFirstPassGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string assemblyCSharpFirstPassEditorGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string builtInPackagesFolderGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string importedPackagesFolderGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string externalPackagesFolderGuid = Guid.NewGuid().ToString(); + + [SerializeField] + private string solutionGuid = Guid.NewGuid().ToString(); + + public bool FullGenerationEnabled + { + get => fullGenerationEnabled; + set + { + fullGenerationEnabled = value; + Save(); + } + } + + internal Guid DependenciesProjectGuid { get; private set; } + + internal Guid AssemblyCSharpGuid { get; private set; } + + internal Guid AssemblyCSharpEditorGuid { get; private set; } + + internal Guid AssemblyCSharpFirstPassGuid { get; private set; } + + internal Guid AssemblyCSharpFirstPassEditorGuid { get; private set; } + + internal Guid BuiltInPackagesFolderGuid { get; private set; } + + internal Guid ImportedPackagesFolderGuid { get; private set; } + + internal Guid ExternalPackagesFolderGuid { get; private set; } + + internal Guid SolutionGuid { get; private set; } + + private void Save() + { + // Ensure directory exists first + Directory.CreateDirectory(Path.GetDirectoryName(MSBuildSettingsFilePath)); + File.WriteAllText(MSBuildSettingsFilePath, EditorJsonUtility.ToJson(this)); + } + + public static MSBuildToolsConfig Load() + { + MSBuildToolsConfig toReturn = new MSBuildToolsConfig(); + + if (File.Exists(MSBuildSettingsFilePath)) + { + EditorJsonUtility.FromJsonOverwrite(File.ReadAllText(MSBuildSettingsFilePath), toReturn); + } + + bool needToSave = false; + + toReturn.DependenciesProjectGuid = EnsureGuid(ref toReturn.dependenciesProjectGuid, ref needToSave); + + toReturn.AssemblyCSharpGuid = EnsureGuid(ref toReturn.assemblyCSharpGuid, ref needToSave); + toReturn.AssemblyCSharpEditorGuid = EnsureGuid(ref toReturn.assemblyCSharpEditorGuid, ref needToSave); + toReturn.AssemblyCSharpFirstPassGuid = EnsureGuid(ref toReturn.assemblyCSharpFirstPassGuid, ref needToSave); + toReturn.AssemblyCSharpFirstPassEditorGuid = EnsureGuid(ref toReturn.assemblyCSharpFirstPassEditorGuid, ref needToSave); + + toReturn.BuiltInPackagesFolderGuid = EnsureGuid(ref toReturn.builtInPackagesFolderGuid, ref needToSave); + toReturn.ImportedPackagesFolderGuid = EnsureGuid(ref toReturn.importedPackagesFolderGuid, ref needToSave); + toReturn.ExternalPackagesFolderGuid = EnsureGuid(ref toReturn.externalPackagesFolderGuid, ref needToSave); + + toReturn.SolutionGuid = EnsureGuid(ref toReturn.solutionGuid, ref needToSave); + + if (CurrentConfigVersion > toReturn.version) + { + toReturn.version = CurrentConfigVersion; + needToSave = true; + } + + if (needToSave) + { + toReturn.Save(); + } + + return toReturn; + } + + private static Guid EnsureGuid(ref string field, ref bool needToSave) + { + if (!Guid.TryParse(field, out Guid guid)) + { + guid = Guid.NewGuid(); + field = guid.ToString(); + + needToSave = true; + } + + return guid; + } + } +} +#endif diff --git a/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs.meta b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs.meta new file mode 100644 index 0000000..1a3f122 --- /dev/null +++ b/Source/MSBuildTools.Unity/Packages/com.microsoft.msbuildforunity/Editor/ProjectGenerator/Scripts/MSBuildToolsConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26b2ef2063bf2f649869c8c12a13295c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: