diff --git a/Assets/NuGet/Editor/NugetHelper.cs b/Assets/NuGet/Editor/NugetHelper.cs index 979110b0..64b43035 100644 --- a/Assets/NuGet/Editor/NugetHelper.cs +++ b/Assets/NuGet/Editor/NugetHelper.cs @@ -499,69 +499,12 @@ private static void Clean(NugetPackageIdentifier package) private static bool IsAlreadyImportedInEngine(NugetPackageIdentifier package) { if (package.IsManuallyInstalled) return false; - HashSet alreadyImportedLibs = GetAlreadyImportedLibs(); + HashSet alreadyImportedLibs = UnityPreImportedLibraryResolver.GetAlreadyImportedLibs(); bool isAlreadyImported = alreadyImportedLibs.Contains(package.Id); LogVerbose("Is package '{0}' already imported? {1}", package.Id, isAlreadyImported); return isAlreadyImported; } - private static HashSet alreadyImportedLibs = null; - private static HashSet GetAlreadyImportedLibs() - { - if (alreadyImportedLibs != null) return alreadyImportedLibs; - - var cachePath = Path.Combine(SystemProxy.CurrentDir, $"../Library/AllLibPaths{SystemProxy.UnityVersion}.txt"); - if (File.Exists(cachePath)) - { - alreadyImportedLibs = new HashSet(File.ReadAllLines(cachePath)); - } - else - { - string[] lookupPaths = GetAllLookupPaths(); - IEnumerable libNames = lookupPaths - .SelectMany(directory => Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories)) - .Select(Path.GetFileName) - .Select(p => Path.ChangeExtension(p, null)); - alreadyImportedLibs = new HashSet(libNames); - if (!Directory.Exists("../Library/")) Directory.CreateDirectory("../Library/"); - File.WriteAllLines(cachePath, alreadyImportedLibs); - LogVerbose("Already imported libs: {0}", string.Join(", ", alreadyImportedLibs)); - } - - return alreadyImportedLibs; - } - - private static string[] GetAllLookupPaths() - { - var executablePath = SystemProxy.AppDir; - var roots = new[] { - // MacOS directory layout - Path.Combine(executablePath, "Contents"), - Path.GetDirectoryName(Path.GetDirectoryName(executablePath)), - // Windows directory layout - Path.Combine(Directory.GetParent(executablePath).FullName, "Data") - }; - var relativePaths = new[] { - Path.Combine("NetStandard", "compat"), - Path.Combine("MonoBleedingEdge", "lib", "mono") - }; - var allPossiblePaths = roots - .SelectMany(root => relativePaths - .Select(relativePath => Path.Combine(root, relativePath))); - var existingPaths = allPossiblePaths - .Where(Directory.Exists) - .ToArray(); - if (existingPaths.Length == 0) - { - LogVerbose("No existing path for dependency lookup found in roots: {0}", string.Join(", ", roots)); - } - else - { - LogVerbose("All existing path to dependency lookup are: {0}", string.Join(", ", existingPaths)); - } - return existingPaths; - } - public static NugetFrameworkGroup GetBestDependencyFrameworkGroupForCurrentSettings(NugetPackage package) { var targetFrameworks = package.Dependencies.Select(x => x.TargetFramework); @@ -1462,21 +1405,24 @@ public static bool Install(NugetPackage package, bool refreshAssets = true) // look to see if the package (any version) is already installed - SystemProxy.DisplayProgress($"Installing {package.Id} {package.Version}", "Installing Dependencies", 0.1f); - - // install all dependencies for target framework - var frameworkGroup = GetBestDependencyFrameworkGroupForCurrentSettings(package); - - LogVerbose("Installing dependencies for TargetFramework: {0}", frameworkGroup.TargetFramework); - foreach (var dependency in frameworkGroup.Dependencies) + if (InstallDependencies) { - LogVerbose("Installing Dependency: {0} {1}", dependency.Id, dependency.Version); + SystemProxy.DisplayProgress($"Installing {package.Id} {package.Version}", "Installing Dependencies", 0.1f); - var installed = InstallIdentifier(dependency, false); - if (!installed) + // install all dependencies for target framework + var frameworkGroup = GetBestDependencyFrameworkGroupForCurrentSettings(package); + + LogVerbose("Installing dependencies for TargetFramework: {0}", frameworkGroup.TargetFramework); + foreach (var dependency in frameworkGroup.Dependencies) { - SystemProxy.LogError($"Failed to install dependency: {dependency.Id} {dependency.Version}."); - return false; + LogVerbose("Installing Dependency: {0} {1}", dependency.Id, dependency.Version); + + var installed = InstallIdentifier(dependency, false); + if (!installed) + { + SystemProxy.LogError($"Failed to install dependency: {dependency.Id} {dependency.Version}."); + return false; + } } } @@ -1627,7 +1573,9 @@ public static bool Install(NugetPackage package, bool refreshAssets = true) return installSuccess; } - + + internal static bool InstallDependencies { get; set; } = true; + private static string PackageIdToMethodName(string pkgId, string packageTitle = "") { pkgId = pkgId.Replace("nordeus.", "").Replace("unity.", ""); diff --git a/Assets/NuGet/Editor/NugetPreferences.cs b/Assets/NuGet/Editor/NugetPreferences.cs index df1743ad..d69f01cd 100644 --- a/Assets/NuGet/Editor/NugetPreferences.cs +++ b/Assets/NuGet/Editor/NugetPreferences.cs @@ -12,7 +12,7 @@ public static class NugetPreferences /// /// The current version of NuGet for Unity. /// - public const string NuGetForUnityVersion = "3.0.9"; + public const string NuGetForUnityVersion = "3.0.10"; /// /// The current position of the scroll bar in the GUI. diff --git a/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs b/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs new file mode 100644 index 00000000..a127bcca --- /dev/null +++ b/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +#if UNITY_EDITOR +using UnityEditor; +using UnityEditor.Compilation; +#endif + +namespace NugetForUnity +{ + /// + /// Helper to resolve what libraries are already known / imported by unity. + /// + internal static class UnityPreImportedLibraryResolver + { + private static HashSet alreadyImportedLibs; + + private static HashSet alreadyImportedEditorOnlyLibraries; + + /// + /// Gets all libraries that are already imported by unity so we shouldn't / don't need to install them as NuGet packages. + /// + /// A set of all names of libraries that are already imported by unity. + internal static HashSet GetAlreadyImportedLibs() + { + if (alreadyImportedLibs != null) + { + return alreadyImportedLibs; + } +#if UNITY_EDITOR + // Find all the assemblies already installed by NuGetForUnity + var alreadyInstalledDllFileNames = new HashSet(); + + if (NugetHelper.NugetConfigFile != null && Directory.Exists(NugetHelper.NugetConfigFile.RepositoryPath)) + { + alreadyInstalledDllFileNames = new HashSet( + Directory.EnumerateFiles(NugetHelper.NugetConfigFile.RepositoryPath, "*.dll", SearchOption.AllDirectories) + .Select(Path.GetFileNameWithoutExtension)); + } + + // Search the all project assemblies that are not editor only. + // We only use player assemblies as we don't need to collect UnityEditor assemblies, we don't support installing NuGet packages with reference to UnityEditor. +#if UNITY_2019_3_OR_NEWER + const AssembliesType assemblieType = AssembliesType.PlayerWithoutTestAssemblies; +#else + const AssembliesType assemblieType = AssembliesType.Player; +#endif + var projectAssemblies = CompilationPipeline.GetAssemblies(assemblieType) + .Where(playerAssembly => playerAssembly.flags != AssemblyFlags.EditorAssembly); + + // Collect all referenced assemblies but exclude all assemblies installed by NuGetForUnity. + var porojectReferences = projectAssemblies.SelectMany(playerAssembly => playerAssembly.allReferences); + alreadyImportedLibs = new HashSet( + porojectReferences.Select(compiledAssemblyReference => Path.GetFileNameWithoutExtension(compiledAssemblyReference)) + .Where(assemblyName => !alreadyInstalledDllFileNames.Contains(assemblyName))); + + if (PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) + { + // mark NuGet packages that contain the .net standard references as already imported + alreadyImportedLibs.Add("NETStandard.Library"); + alreadyImportedLibs.Add("Microsoft.NETCore.Platforms"); + } + + // the compiler / language is available by default + alreadyImportedLibs.Add("Microsoft.CSharp"); + + var editorOnlyAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor) + .Where(assembly => assembly.flags == AssemblyFlags.EditorAssembly) + .ToList(); + var editorReferences = editorOnlyAssemblies.SelectMany(editorOnlyAssembly => editorOnlyAssembly.allReferences); + alreadyImportedEditorOnlyLibraries = new HashSet( + editorReferences.Select(Path.GetFileNameWithoutExtension).Where(assemblyName => !alreadyImportedLibs.Contains(assemblyName))); + + // com.unity.visualscripting uses .net 4.8 so it implicitly has System.CodeDom + if (!alreadyImportedLibs.Contains("System.CodeDom") && + editorOnlyAssemblies.Any(editorOnlyAssembly => editorOnlyAssembly.name == "Unity.VisualScripting.Shared.Editor")) + { + alreadyImportedEditorOnlyLibraries.Add("System.CodeDom"); + } + + NugetHelper.LogVerbose("Already imported libs: {0}", string.Join(", ", alreadyImportedLibs)); + NugetHelper.LogVerbose("Already imported editor only libraries: {0}", string.Join(", ", alreadyImportedEditorOnlyLibraries)); +#endif + return alreadyImportedLibs; + } + + /// + /// + /// + internal static HashSet GetAlreadyImportedEditorOnlyLibraries() + { + if (alreadyImportedEditorOnlyLibraries == null) + { + GetAlreadyImportedLibs(); + } + + return alreadyImportedEditorOnlyLibraries; + } + } +} diff --git a/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs.meta b/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs.meta new file mode 100644 index 00000000..c4d62e00 --- /dev/null +++ b/Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f8f552637666e543810584c11364756 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/CLI/nugetfu/Program.cs b/CLI/nugetfu/Program.cs index 1ca727cf..411ee809 100644 --- a/CLI/nugetfu/Program.cs +++ b/CLI/nugetfu/Program.cs @@ -18,6 +18,9 @@ public static int Main(string[] args) SystemProxy.AppDir = args[1].Replace("'", "").Replace("\"", ""); } + // need to disable dependency installation as UnityPreImportedLibraryResolver.GetAlreadyImportedLibs is not working outside Unity. + NugetHelper.InstallDependencies = false; + return NugetHelper.Restore() ? 0 : 1; } diff --git a/CLI/nugetfu/nugetfu.csproj b/CLI/nugetfu/nugetfu.csproj index 3a213732..61093250 100644 --- a/CLI/nugetfu/nugetfu.csproj +++ b/CLI/nugetfu/nugetfu.csproj @@ -44,6 +44,9 @@ JunctionPoint.cs + + UnityPreImportedLibraryResolver.cs + diff --git a/CreateDLL/CreateDLL.csproj b/CreateDLL/CreateDLL.csproj index a509185a..6d2b1d2e 100644 --- a/CreateDLL/CreateDLL.csproj +++ b/CreateDLL/CreateDLL.csproj @@ -20,7 +20,7 @@ full false bin\Debug\ - DEBUG;TRACE + DEBUG;TRACE;UNITY_EDITOR; prompt 4 false @@ -29,7 +29,7 @@ pdbonly true bin\Release\ - TRACE + TRACE;UNITY_EDITOR; prompt 4 false @@ -110,6 +110,9 @@ UnityAssetProcessor.cs + + UnityPreImportedLibraryResolver.cs + diff --git a/Packager/NuGetForUnity.unitypackage b/Packager/NuGetForUnity.unitypackage index e62e1cfc..c99a7fa1 100644 Binary files a/Packager/NuGetForUnity.unitypackage and b/Packager/NuGetForUnity.unitypackage differ