internal static TargetAssembly GetCustomTargetAssembly(string scriptPath, string projectDirectory, TargetAssembly[] customTargetAssemblies)
        {
            if (customTargetAssemblies == null)
            {
                return(null);
            }

            int            highestPathDepth = -1;
            TargetAssembly resultAssembly   = null;

            // CustomScriptAssembly paths are absolute, so we convert the scriptPath to an absolute path, if necessary.
            bool isPathAbsolute = AssetPath.IsPathRooted(scriptPath);
            var  lowerFullPath  = isPathAbsolute ? AssetPath.GetFullPath(scriptPath).ToLower() : AssetPath.Combine(projectDirectory, scriptPath).ToLower();

            foreach (var assembly in customTargetAssemblies)
            {
                int pathDepth = assembly.PathFilter(lowerFullPath);

                if (pathDepth <= highestPathDepth)
                {
                    continue;
                }

                resultAssembly   = assembly;
                highestPathDepth = pathDepth;
            }

            return(resultAssembly);
        }
        public void Start()
        {
            var runner = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "ILPostProcessorRunner", "ILPostProcessorRunner.exe");

            if (!File.Exists(runner))
            {
                throw new Exception(string.Format($"'{runner}' not found. Is your Unity installation corrupted?"));
            }

            var assemblyPath            = AssetPath.GetFullPath(AssetPath.Combine(tempOutputDirectory, Assembly.Filename));
            var assemblyReferencesPaths = Assembly.GetAllReferences().ToArray();
            var assemblyFolderPaths     = ilPostProcessing.AssemblySearchPaths;

            var outputDirectory    = AssetPath.GetFullPath(tempOutputDirectory);
            var postProcessorPaths = ilPostProcessing.PostProcessorAssemblyPaths;

            var arguments = new List <string>
            {
                $"-a \"{assemblyPath}\"",
                $"-f \"{string.Join(",", assemblyFolderPaths)}\"",
                $"-r \"{string.Join(",", assemblyReferencesPaths)}\"",
                $"-d \"{string.Join(",", Assembly.Defines)}\"",
                $"-p \"{string.Join(",", postProcessorPaths)}\"",
                $"-o \"{outputDirectory}\"",
            };

            var responseFilePath = PrepareFileName(AssetPath.GetFullPath(CommandLineFormatter.GenerateResponseFile(arguments)));

            var args = $"@{responseFilePath}";

            // Always run on Mono until all ILPostProcessors have been fixed
            // to run on NET Core.
            //if (NetCoreRunProgram.IsSupported())
            //{
            //    process = new NetCoreRunProgram(runner, args, null);
            //}
            //else
            {
                process = new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, runner, args, false, null);
            }

            process.Start();
        }
        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();
        }
        public void SetAllCustomScriptAssemblyReferenceJsonsContents(string[] paths, string[] contents)
        {
            var assemblyRefs = new List <CustomScriptAssemblyReference>();
            var exceptions   = new List <Exception>();

            // We only construct this lookup if it is required, which is when we are using guids instead of assembly names.
            Dictionary <string, CustomScriptAssembly> guidsToAssemblies = 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 = m_SkipCustomScriptAssemblyGraphValidation ?
                                         null :
                                         CustomScriptAssemblies.GroupBy(x => x.PathPrefix).ToDictionary(x => x.First().PathPrefix, x => new List <string>()
            {
                x.First().FilePath
            }, StringComparer.OrdinalIgnoreCase);

            for (var i = 0; i < paths.Length; ++i)
            {
                var path = paths[i];

                CustomScriptAssemblyReference loadedCustomScriptAssemblyReference = null;

                try
                {
                    var fullPath = AssetPath.IsPathRooted(path) ? AssetPath.GetFullPath(path) : AssetPath.Combine(m_ProjectDirectory, path);

                    if (contents != null)
                    {
                        var jsonContents = contents[i];
                        loadedCustomScriptAssemblyReference = LoadCustomScriptAssemblyReferenceFromJson(fullPath, jsonContents);
                    }
                    else
                    {
                        loadedCustomScriptAssemblyReference = LoadCustomScriptAssemblyReferenceFromJsonPath(fullPath);
                    }

                    if (!m_SkipCustomScriptAssemblyGraphValidation)
                    {
                        // Check both asmdef and asmref files.
                        if (prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssemblyReference.PathPrefix, out var duplicateFilePaths))
                        {
                            var filePaths = new List <string> {
                                loadedCustomScriptAssemblyReference.FilePath
                            };
                            filePaths.AddRange(duplicateFilePaths);

                            throw new AssemblyDefinitionException(
                                      $"Folder '{loadedCustomScriptAssemblyReference.PathPrefix}' contains multiple assembly definition files", filePaths.ToArray());
                        }
                    }

                    // Convert GUID references to assembly names
                    if (GUIDReference.IsGUIDReference(loadedCustomScriptAssemblyReference.Reference))
                    {
                        // Generate the guid to assembly lookup?
                        guidsToAssemblies = guidsToAssemblies ?? CustomScriptAssemblies.ToDictionary(x => x.GUID);

                        var guid = Utility.FastToLower(GUIDReference.GUIDReferenceToGUID(loadedCustomScriptAssemblyReference.Reference));
                        if (guidsToAssemblies.TryGetValue(guid, out var foundAssembly))
                        {
                            loadedCustomScriptAssemblyReference.Reference = foundAssembly.Name;
                        }
                    }
                }
                catch (Exception e)
                {
                    m_CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError);
                    exceptions.Add(e);
                }

                if (loadedCustomScriptAssemblyReference != null)
                {
                    assemblyRefs.Add(loadedCustomScriptAssemblyReference);

                    if (m_SkipCustomScriptAssemblyGraphValidation)
                    {
                        continue;
                    }

                    if (!prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssemblyReference.PathPrefix, out var duplicateFilePaths))
                    {
                        duplicateFilePaths = new List <string>();
                        prefixToFilePathLookup[loadedCustomScriptAssemblyReference.PathPrefix] = duplicateFilePaths;
                    }

                    duplicateFilePaths.Add(loadedCustomScriptAssemblyReference.FilePath);
                }
            }

            CustomScriptAssemblyReferences = assemblyRefs;
            Exceptions = exceptions.ToArray();
        }