private static AssemblyData AssemblyDataFrom(ScriptAssembly a, ScriptAssembly[] allAssemblies, int index) { Array.Sort(a.Files, StringComparer.InvariantCulture); var references = a.ScriptAssemblyReferences.Select(r => Array.IndexOf(allAssemblies, r)).ToArray(); Array.Sort(references); return(new AssemblyData { Name = new NPath(a.Filename).FileNameWithoutExtension, SourceFiles = a.Files, Defines = a.Defines, PrebuiltReferences = a.References, References = references, AllowUnsafeCode = a.CompilerOptions.AllowUnsafeCode, RuleSet = a.CompilerOptions.RoslynAnalyzerRulesetPath, LanguageVersion = a.CompilerOptions.LanguageVersion, Analyzers = a.CompilerOptions.RoslynAnalyzerDllPaths, UseDeterministicCompilation = a.CompilerOptions.UseDeterministicCompilation, SuppressCompilerWarnings = (a.Flags & AssemblyFlags.SuppressCompilerWarnings) != 0, Asmdef = a.AsmDefPath, CustomCompilerOptions = a.CompilerOptions.AdditionalCompilerArguments, BclDirectories = MonoLibraryHelpers.GetSystemReferenceDirectories(a.CompilerOptions.ApiCompatibilityLevel), DebugIndex = index, SkipCodeGen = a.SkipCodeGen }); }
public void SetAllCustomScriptAssemblyJsonContents(string[] paths, string[] contents, string[] guids) { var assemblies = new List <CustomScriptAssembly>(); var assemblyLowercaseNamesLookup = new Dictionary <string, CustomScriptAssembly>(); var exceptions = new List <Exception>(); var guidsToAssemblies = new Dictionary <string, CustomScriptAssembly>(); HashSet <string> predefinedAssemblyNames = null; // To check if a path prefix is already being used we use a Dictionary where the key is the prefix and the value is the file path. var prefixToFilePathLookup = CustomScriptAssemblyReferences.ToDictionary(x => x.PathPrefix, x => new List <string> { x.FilePath }, StringComparer.OrdinalIgnoreCase); m_CompilationSetupErrorsTracker.ClearCompilationSetupErrors(CompilationSetupErrors.LoadError); // Load first to setup guidsToAssemblies dictionary and convert guids to assembly names // before checking for assembly reference errors, so errors emit assembly names instead of guids. for (var i = 0; i < paths.Length; ++i) { var path = paths[i]; var guid = guids[i]; string lowerCaseName = null; CustomScriptAssembly loadedCustomScriptAssembly = null; try { var fullPath = AssetPath.IsPathRooted(path) ? AssetPath.GetFullPath(path) : AssetPath.Combine(m_ProjectDirectory, path); loadedCustomScriptAssembly = contents != null ? LoadCustomScriptAssemblyFromJson(fullPath, contents[i], guid) : LoadCustomScriptAssemblyFromJsonPath(fullPath, guid); loadedCustomScriptAssembly.References = loadedCustomScriptAssembly.References ?? new string[0]; lowerCaseName = Utility.FastToLower(loadedCustomScriptAssembly.Name); guidsToAssemblies[Utility.FastToLower(guid)] = loadedCustomScriptAssembly; if (!m_SkipCustomScriptAssemblyGraphValidation) { if (predefinedAssemblyNames == null) { predefinedAssemblyNames = new HashSet <string>(EditorBuildRules.PredefinedTargetAssemblyNames); var netfw = MonoLibraryHelpers .GetSystemLibraryReferences(ApiCompatibilityLevel.NET_Unity_4_8).Select(Path.GetFileNameWithoutExtension); var netstandard21 = MonoLibraryHelpers .GetSystemLibraryReferences(ApiCompatibilityLevel.NET_Standard).Select(Path.GetFileNameWithoutExtension); predefinedAssemblyNames.UnionWith(netfw); predefinedAssemblyNames.UnionWith(netstandard21); } CheckPredefinedAssemblyNames( predefinedAssemblyNames, assemblyLowercaseNamesLookup, lowerCaseName, prefixToFilePathLookup, ref loadedCustomScriptAssembly); } } catch (Exception e) { m_CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError); exceptions.Add(e); } if (loadedCustomScriptAssembly == null || m_SkipCustomScriptAssemblyGraphValidation && assemblyLowercaseNamesLookup.ContainsKey(lowerCaseName)) { continue; } loadedCustomScriptAssembly.References = loadedCustomScriptAssembly.References ?? new string[0]; assemblyLowercaseNamesLookup[lowerCaseName] = loadedCustomScriptAssembly; assemblies.Add(loadedCustomScriptAssembly); if (!prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssembly.PathPrefix, out var duplicateFilePaths)) { duplicateFilePaths = new List <string>(); prefixToFilePathLookup[loadedCustomScriptAssembly.PathPrefix] = duplicateFilePaths; } duplicateFilePaths.Add(loadedCustomScriptAssembly.FilePath); } ConvertGUIDReferencesToAssemblyNames(assemblies, guidsToAssemblies); if (!m_SkipCustomScriptAssemblyGraphValidation) { CheckForReferenceErrors(assemblies, exceptions); } CustomScriptAssemblies = assemblies.ToArray(); Exceptions = exceptions.ToArray(); }
internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, ScriptAssemblySettings settings, CompilationAssemblies assemblies, IDictionary <TargetAssembly, ScriptAssembly> targetToScriptAssembly, ICompilationSetupWarningTracker warningSink) { var scriptAssemblyReferences = new List <ScriptAssembly>(targetAssembly.References.Count); var references = new List <string>(); bool buildingForEditor = settings.BuildingForEditor; bool noEngineReferences = (targetAssembly.Flags & AssemblyFlags.NoEngineReferences) == AssemblyFlags.NoEngineReferences; bool shouldProcessPredefinedCustomTargets = assemblies.CustomTargetAssemblies != null && (targetAssembly.Type & TargetAssemblyType.Predefined) == TargetAssemblyType.Predefined; var predefinedCustomTargetReferences = Enumerable.Empty <TargetAssembly>(); if (shouldProcessPredefinedCustomTargets && assemblies.PredefinedAssembliesCustomTargetReferences != null) { predefinedCustomTargetReferences = assemblies.PredefinedAssembliesCustomTargetReferences; } var unityReferences = new Dictionary <string, string>(); // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) references, as long as the target // doesn't specify that it doesn't want them. if (!noEngineReferences) { // Add predefined custom target references in a hash-set for fast lookup var predefinedCustomTargetRefs = new HashSet <string>(predefinedCustomTargetReferences.Select(x => x.Filename)); unityReferences = GetUnityReferences(scriptAssembly, targetAssembly, assemblies.UnityAssemblies, predefinedCustomTargetRefs, settings.CompilationOptions, UnityReferencesOptions.None); references.AddRange(unityReferences.Values); } AddTestRunnerCustomReferences(ref targetAssembly, assemblies.CustomTargetAssemblies); // Setup target assembly references foreach (var reference in targetAssembly.References) { ScriptAssembly scriptAssemblyReference; // If the assembly already showed up in the unity references, don't reference it here. // This can happen when an assembly is configured as a unity assembly override, but // overrides are disabled. The Unity assembly should take precedence in that case. if (unityReferences.ContainsKey(reference.Filename)) { continue; } // Add ScriptAssembly references to other dirty script assemblies that also need to be rebuilt. if (targetToScriptAssembly.TryGetValue(reference, out scriptAssemblyReference)) { System.Diagnostics.Debug.Assert(scriptAssemblyReference != null); scriptAssemblyReferences.Add(scriptAssemblyReference); } } // For predefined target assembly add references to custom target assemblies if (shouldProcessPredefinedCustomTargets) { foreach (var customTargetAssembly in predefinedCustomTargetReferences) { ScriptAssembly scriptAssemblyReference; // Only add ScriptAssembly reference if the custom target assembly is dirty, e.g. is in targetToScriptAssembly dictionary // Otherwise just add already compiled custom target assembly as precompiled reference. if (targetToScriptAssembly.TryGetValue(customTargetAssembly, out scriptAssemblyReference)) { scriptAssemblyReferences.Add(scriptAssemblyReference); } } } // Add pre-compiled assemblies as references var allPrecompiledAssemblies = assemblies.PrecompiledAssemblies ?? new Dictionary <string, PrecompiledAssembly>(0); List <PrecompiledAssembly> precompiledReferences = new List <PrecompiledAssembly>(allPrecompiledAssemblies.Count); var explicitPrecompiledReferences = new List <PrecompiledAssembly>(targetAssembly.ExplicitPrecompiledReferences.Count); if ((targetAssembly.Flags & AssemblyFlags.ExplicitReferences) == AssemblyFlags.ExplicitReferences) { if (!noEngineReferences) { precompiledReferences.AddRange(allPrecompiledAssemblies .Where(x => (x.Value.Flags & AssemblyFlags.UserAssembly) != AssemblyFlags.UserAssembly) .Select(x => x.Value)); } foreach (var explicitPrecompiledReference in targetAssembly.ExplicitPrecompiledReferences) { PrecompiledAssembly assembly; if (allPrecompiledAssemblies.TryGetValue(explicitPrecompiledReference, out assembly)) { explicitPrecompiledReferences.Add(assembly); } } } else { var precompiledAssemblies = allPrecompiledAssemblies.Values.Where(x => (x.Flags & AssemblyFlags.ExplicitlyReferenced) != AssemblyFlags.ExplicitlyReferenced).ToList(); // if noEngineReferences, add just the non-explicitly-referenced user assemblies if (noEngineReferences) { precompiledReferences.AddRange(precompiledAssemblies.Where(x => (x.Flags & AssemblyFlags.UserAssembly) == AssemblyFlags.UserAssembly)); } else { precompiledReferences.AddRange(precompiledAssemblies); } } AddTestRunnerPrecompiledReferences(targetAssembly, allPrecompiledAssemblies, ref precompiledReferences); var precompiledReferenceNames = GetPrecompiledReferences(scriptAssembly, targetAssembly.Type, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledReferences, explicitPrecompiledReferences, warningSink); references.AddRange(precompiledReferenceNames); if (buildingForEditor && assemblies.EditorAssemblyReferences != null) { references.AddRange(assemblies.EditorAssemblyReferences); } references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.CompilerOptions.ApiCompatibilityLevel)); scriptAssembly.ScriptAssemblyReferences = scriptAssemblyReferences.ToArray(); scriptAssembly.References = references.ToArray(); }
internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, ScriptAssemblySettings settings, CompilationAssemblies assemblies, IDictionary <TargetAssembly, ScriptAssembly> targetToScriptAssembly, string filenameSuffix) { var scriptAssemblyReferences = new List <ScriptAssembly>(); var references = new List <string>(); bool buildingForEditor = settings.BuildingForEditor; // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) referencees. var unityReferences = GetUnityReferences(scriptAssembly, assemblies.UnityAssemblies, settings.CompilationOptions); references.AddRange(unityReferences); // Setup target assembly references foreach (var reference in targetAssembly.References) { ScriptAssembly scriptAssemblyReference; // Add ScriptAssembly references to other dirty script assemblies that also need to be rebuilt. if (targetToScriptAssembly.TryGetValue(reference, out scriptAssemblyReference)) { System.Diagnostics.Debug.Assert(scriptAssemblyReference != null); scriptAssemblyReferences.Add(scriptAssemblyReference); } else { // Add string references to other assemblies that do not need to be rebuilt. var assemblyPath = reference.FullPath(settings.OutputDirectory, filenameSuffix); if (File.Exists(assemblyPath)) { references.Add(assemblyPath); } } } // For predefined target assembly add references to custom target assemblies if (assemblies.CustomTargetAssemblies != null && (targetAssembly.Type & TargetAssemblyType.Predefined) == TargetAssemblyType.Predefined) { foreach (var customTargetAssembly in assemblies.PredefinedAssembliesCustomTargetReferences ?? Enumerable.Empty <TargetAssembly>()) { ScriptAssembly scriptAssemblyReference; // Only add ScriptAssembly reference if the custom target assembly is dirty, e.g. is in targetToScriptAssembly dictionary // Otherwise just add already compiled custom target assembly as precompiled reference. if (targetToScriptAssembly.TryGetValue(customTargetAssembly, out scriptAssemblyReference)) { scriptAssemblyReferences.Add(scriptAssemblyReference); } else { var customTargetAssemblyPath = customTargetAssembly.FullPath(settings.OutputDirectory, filenameSuffix); // File might not exist if there are no scripts in the custom target assembly folder. if (File.Exists(customTargetAssemblyPath)) { references.Add(customTargetAssemblyPath); } } } } // Add pre-compiled assemblies as references PrecompiledAssembly[] precompiledAssembliesForReferences = assemblies.PrecompiledAssemblies ?? new PrecompiledAssembly[] {}; if (settings.OptionalUnityReferences != OptionalUnityReferences.None) { precompiledAssembliesForReferences = precompiledAssembliesForReferences.Where(x => x.OptionalUnityReferences == OptionalUnityReferences.None || ((targetAssembly.OptionalUnityReferences & x.OptionalUnityReferences & settings.OptionalUnityReferences) != 0)).ToArray(); } var precompiledReferences = GetPrecompiledReferences(scriptAssembly, targetAssembly.Type, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledAssembliesForReferences); references.AddRange(precompiledReferences); if (buildingForEditor && assemblies.EditorAssemblyReferences != null) { references.AddRange(assemblies.EditorAssemblyReferences); } references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename)); scriptAssembly.ScriptAssemblyReferences = scriptAssemblyReferences.ToArray(); scriptAssembly.References = references.ToArray(); }