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)); }
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); }
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(); }
internal static ScriptAssembly[] ToScriptAssemblies(IDictionary <TargetAssembly, HashSet <string> > targetAssemblies, ScriptAssemblySettings settings, CompilationAssemblies assemblies, HashSet <string> runUpdaterAssemblies) { var scriptAssemblies = new ScriptAssembly[targetAssemblies.Count]; var targetToScriptAssembly = new Dictionary <TargetAssembly, ScriptAssembly>(); int index = 0; bool buildingForEditor = settings.BuildingForEditor; foreach (var entry in targetAssemblies) { var targetAssembly = entry.Key; var sourceFiles = 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.Language = targetAssembly.Language; var editorOnlyTargetAssembly = (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; if (editorOnlyTargetAssembly || (buildingForEditor && settings.ApiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6)) { scriptAssembly.ApiCompatibilityLevel = (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? ApiCompatibilityLevel.NET_4_6 : ApiCompatibilityLevel.NET_2_0; } else { scriptAssembly.ApiCompatibilityLevel = settings.ApiCompatibilityLevel; } if (!string.IsNullOrEmpty(settings.FilenameSuffix)) { var basename = AssetPath.GetAssemblyNameWithoutExtension(targetAssembly.Filename); scriptAssembly.Filename = string.Concat(basename, settings.FilenameSuffix, ".dll"); } else { scriptAssembly.Filename = targetAssembly.Filename; } if (runUpdaterAssemblies != null && runUpdaterAssemblies.Contains(scriptAssembly.Filename)) { scriptAssembly.RunUpdater = true; } scriptAssembly.OutputDirectory = settings.OutputDirectory; scriptAssembly.Defines = settings.Defines; scriptAssembly.Files = sourceFiles.ToArray(); if (targetAssembly.Type == TargetAssemblyType.Predefined) { scriptAssembly.CompilerOptions = settings.PredefinedAssembliesCompilerOptions; } else { scriptAssembly.CompilerOptions = targetAssembly.CompilerOptions; } // Script files must always be passed in the same order to the compiler. // Otherwise player builds might fail for partial classes. Array.Sort(scriptAssembly.Files); } // Setup ScriptAssembly references index = 0; foreach (var entry in targetAssemblies) { AddScriptAssemblyReferences(ref scriptAssemblies[index++], entry.Key, settings, assemblies, targetToScriptAssembly, settings.FilenameSuffix); } return(scriptAssemblies); }
public static ScriptAssembly[] GetAllScriptAssemblies(IEnumerable <string> allSourceFiles, string projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies, TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined) { if (allSourceFiles == null || allSourceFiles.Count() == 0) { return(new ScriptAssembly[0]); } var targetAssemblyFiles = new Dictionary <TargetAssembly, HashSet <string> >(); foreach (var scriptFile in allSourceFiles) { var targetAssembly = GetTargetAssembly(scriptFile, projectDirectory, assemblies.CustomTargetAssemblies); if (!IsCompatibleWithPlatform(targetAssembly, settings)) { continue; } // Optionally only include specific TargetAssemblyType assemblies. if (onlyIncludeType != TargetAssemblyType.Undefined && targetAssembly.Type != onlyIncludeType) { continue; } var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(scriptFile); var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) { targetAssembly.Language = scriptLanguage; } HashSet <string> assemblySourceFiles; if (!targetAssemblyFiles.TryGetValue(targetAssembly, out assemblySourceFiles)) { assemblySourceFiles = new HashSet <string>(); targetAssemblyFiles[targetAssembly] = assemblySourceFiles; } assemblySourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile)); } return(ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, null)); }