public static ScriptAssembly[] GetAllScriptAssemblies( Dictionary <string, string> allSourceFiles, String projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies, ISafeModeInfo safeModeInfo, TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined, Func <TargetAssembly, bool> targetAssemblyCondition = null, ICompilationSetupWarningTracker warningSink = null) { if (allSourceFiles == null || allSourceFiles.Count == 0) { return(new ScriptAssembly[0]); } var targetAssemblyFiles = new Dictionary <TargetAssembly, DirtyTargetAssembly>(); foreach (var entry in allSourceFiles) { var scriptFile = entry.Key; var assemblyName = entry.Value; var targetAssembly = GetTargetAssembly(scriptFile, assemblyName, projectDirectory, assemblies.CustomTargetAssemblies); if (targetAssembly == null) { continue; } if (!IsCompatibleWithPlatformAndDefines(targetAssembly, settings)) { continue; } if (targetAssemblyCondition != null && !targetAssemblyCondition(targetAssembly)) { continue; } // Optionally only include specific TargetAssemblyType assemblies. if (onlyIncludeType != TargetAssemblyType.Undefined && targetAssembly.Type != onlyIncludeType) { continue; } DirtyTargetAssembly dirtyTargetAssembly; if (!targetAssemblyFiles.TryGetValue(targetAssembly, out dirtyTargetAssembly)) { dirtyTargetAssembly = new DirtyTargetAssembly(); targetAssemblyFiles[targetAssembly] = dirtyTargetAssembly; } dirtyTargetAssembly.SourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile)); } return(ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, warningSink, safeModeInfo)); }
public static List <string> GetPrecompiledReferences(ScriptAssembly scriptAssembly, TargetAssemblyType targetAssemblyType, EditorScriptCompilationOptions options, EditorCompatibility editorCompatibility, IEnumerable <PrecompiledAssembly> implicitPrecompiledAssemblies, IEnumerable <PrecompiledAssembly> explicitPrecompiledAssemblies, ICompilationSetupWarningTracker warningSink) { var references = new List <string>(); bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; bool isCustomAssembly = (targetAssemblyType & TargetAssemblyType.Custom) == TargetAssemblyType.Custom; void AddReferenceIfMatchBuildTargetAndEditorFlag(PrecompiledAssembly precompiledAssembly, bool explicitReference) { bool compiledAssemblyEditorOnly = (precompiledAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; // Add all pre-compiled runtime assemblies as references to all script assemblies. Don't add pre-compiled editor assemblies as dependencies to runtime assemblies. if (!compiledAssemblyEditorOnly || assemblyEditorOnly || (isCustomAssembly && buildingForEditor && editorCompatibility == EditorCompatibility.CompatibleWithEditor)) { if (IsPrecompiledAssemblyCompatibleWithBuildTarget(precompiledAssembly, scriptAssembly.BuildTarget)) { references.Add(precompiledAssembly.Path); } // we don't warn on build target mismatch, as this is actually a common pattern (an asmdef with multiple references to different "target-specific" assemblies with the same symbols - e.g. foo.XboxOne.dll, foo.PS5.dll, foo.WebGL.dll) } else if (explicitReference && !string.IsNullOrEmpty(scriptAssembly.AsmDefPath)) { warningSink?.AddAssetWarning(scriptAssembly.AsmDefPath, $"{scriptAssembly.Filename}: can't add reference to {precompiledAssembly.Path} as it is an editor-only assembly"); } } if (implicitPrecompiledAssemblies != null) { foreach (var precompiledAssembly in implicitPrecompiledAssemblies) { AddReferenceIfMatchBuildTargetAndEditorFlag(precompiledAssembly, false); } } if (explicitPrecompiledAssemblies != null) { foreach (var precompiledAssembly in explicitPrecompiledAssemblies) { AddReferenceIfMatchBuildTargetAndEditorFlag(precompiledAssembly, true); } } return(references); }
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 ScriptAssembly[] ToScriptAssemblies( IDictionary <TargetAssembly, DirtyTargetAssembly> targetAssemblies, ScriptAssemblySettings settings, CompilationAssemblies assemblies, ICompilationSetupWarningTracker warningSink, ISafeModeInfo safeModeInfo) { var scriptAssemblies = new ScriptAssembly[targetAssemblies.Count]; var targetToScriptAssembly = new Dictionary <TargetAssembly, ScriptAssembly>(); int index = 0; bool buildingForEditor = settings.BuildingForEditor; var safeModeWhiteList = new HashSet <string>(safeModeInfo.GetWhiteListAssemblyNames()); foreach (var entry in targetAssemblies) { var targetAssembly = entry.Key; var dirtyTargetAssembly = entry.Value; var scriptAssembly = new ScriptAssembly(); // Setup TargetAssembly -> ScriptAssembly mapping for converting references scriptAssemblies[index] = scriptAssembly; targetToScriptAssembly[targetAssembly] = scriptAssemblies[index++]; // Setup ScriptAssembly scriptAssembly.Flags = targetAssembly.Flags; scriptAssembly.BuildTarget = settings.BuildTarget; scriptAssembly.OriginPath = targetAssembly.PathPrefix; scriptAssembly.Filename = targetAssembly.Filename; scriptAssembly.SkipCodeGen = safeModeWhiteList.Contains(targetAssembly.Filename); scriptAssembly.RootNamespace = targetAssembly.Type == TargetAssemblyType.Predefined ? settings.ProjectRootNamespace : targetAssembly.RootNamespace; scriptAssembly.OutputDirectory = settings.OutputDirectory; scriptAssembly.Defines = targetAssembly.Defines == null ? s_CSharpVersionDefines : targetAssembly.Defines.Concat(s_CSharpVersionDefines).ToArray(); scriptAssembly.Files = dirtyTargetAssembly.SourceFiles.ToArray(); scriptAssembly.TargetAssemblyType = targetAssembly.Type; scriptAssembly.AsmDefPath = targetAssembly.AsmDefPath; if (scriptAssembly.TargetAssemblyType == TargetAssemblyType.Predefined) { scriptAssembly.CompilerOptions = new ScriptCompilerOptions(settings.PredefinedAssembliesCompilerOptions); } else { scriptAssembly.CompilerOptions = targetAssembly.CompilerOptions; } scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = new string[0]; scriptAssembly.CompilerOptions.RoslynAnalyzerRulesetPath = string.Empty; scriptAssembly.CompilerOptions.AdditionalCompilerArguments = settings.AdditionalCompilerArguments; var editorOnlyTargetAssembly = (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; if (editorOnlyTargetAssembly) { scriptAssembly.CompilerOptions.ApiCompatibilityLevel = ApiCompatibilityLevel.NET_Unity_4_8; } else { scriptAssembly.CompilerOptions.ApiCompatibilityLevel = settings.PredefinedAssembliesCompilerOptions.ApiCompatibilityLevel; } if ((settings.CompilationOptions & EditorScriptCompilationOptions.BuildingUseDeterministicCompilation) == EditorScriptCompilationOptions.BuildingUseDeterministicCompilation) { scriptAssembly.CompilerOptions.UseDeterministicCompilation = true; } else { scriptAssembly.CompilerOptions.UseDeterministicCompilation = false; } scriptAssembly.CompilerOptions.CodeOptimization = settings.CodeOptimization; } // Don't add the auto-referenced engine assemblies if the assembly either has the flag set, or // is a codegen assembly AutoReferencedPackageAssemblies.AddReferences(assemblies.CustomTargetAssemblies, settings.CompilationOptions, t => { var hasNoEngineReferencesFlag = (t.Flags & AssemblyFlags.NoEngineReferences) == AssemblyFlags.NoEngineReferences; if (hasNoEngineReferencesFlag) { return(false); } return(!UnityCodeGenHelpers.IsCodeGen(t.Filename)); }); // Setup ScriptAssembly references index = 0; foreach (var entry in targetAssemblies) { var scriptAssembly = scriptAssemblies[index++]; AddScriptAssemblyReferences(ref scriptAssembly, entry.Key, settings, assemblies, targetToScriptAssembly, warningSink); if (UnityCodeGenHelpers.IsCodeGen(entry.Key.Filename) || UnityCodeGenHelpers.IsCodeGenTest(entry.Key.Filename) || CompilationPipelineCommonHelper.ShouldAdd(entry.Key.Filename)) { CompilationPipelineCommonHelper.UpdateScriptAssemblyReference(ref scriptAssembly); } if (!buildingForEditor) { PlatformSupportModuleHelpers.AddAdditionalPlatformSupportData(settings.CompilationExtension, ref scriptAssembly); } } if ((settings.CompilationOptions & EditorScriptCompilationOptions.BuildingWithRoslynAnalysis) != 0) { var analyzers = assemblies.RoslynAnalyzerDllPaths; foreach (var a in analyzers) { var targetAssemblyOwningAnalyzer = assemblies.CustomTargetAssemblies.Values .OrderBy(c => c.PathFilter(a)).LastOrDefault(); if (targetAssemblyOwningAnalyzer?.PathFilter(a) <= 0) { targetAssemblyOwningAnalyzer = null; } foreach (var scriptAssembly in scriptAssemblies) { if (ShouldUseAnalyzerForScriptAssembly(scriptAssembly, targetAssemblyOwningAnalyzer)) { scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths.Concat(new[] { a }).ToArray(); scriptAssembly.CompilerOptions.RoslynAnalyzerRulesetPath = scriptAssembly.TargetAssemblyType == TargetAssemblyType.Predefined ? RuleSetFileCache.GetRuleSetFilePathInRootFolder(Path.ChangeExtension(scriptAssembly.Filename, null)) : RuleSetFileCache.GetPathForAssembly(scriptAssembly.OriginPath); } } } } return(scriptAssemblies); }