コード例 #1
0
        private static void ProcessInitializeOnLoadAttributes(Type[] types)
        {
            bool reportTimes = (bool)Debug.GetDiagnosticSwitch("EnableDomainReloadTimings").value;

            IEnumerable <Type> sortedTypes;

            using (_profilerMarkerSortTypes.Auto())
            {
                // Sort types according to topologically-sorted assemblies, such that we guarantee that
                // [InitializeOnLoad] classes in assemblies referenced by a given assembly will have been
                // initialized prior to that assembly's own [InitializeOnLoad] classes.
                sortedTypes = types.OrderBy(x => Array.IndexOf(m_topologicallySortedAssemblies, x.Assembly));
            }

            foreach (Type type in sortedTypes)
            {
                using (new EditorPerformanceMarker($"InitializeOnLoad {type.Name}", type).Auto())
                    using (_profilerMarkerProcessInitializeOnLoadAttributes.Auto(reportTimes, () => type.AssemblyQualifiedName))
                    {
                        try
                        {
                            RuntimeHelpers.RunClassConstructor(type.TypeHandle);
                        }
                        catch (TypeInitializationException x)
                        {
                            Debug.LogError(x.InnerException);
                        }
                    }
            }
        }
コード例 #2
0
        private bool ShouldUseIl2CppCore()
        {
            if (!m_PlatformProvider.supportsUsingIl2cppCore)
            {
                return(false);
            }

            var disableIl2CppCoreEnv = System.Environment.GetEnvironmentVariable("UNITY_IL2CPP_DISABLE_NET_CORE");

            if (disableIl2CppCoreEnv == "1")
            {
                return(false);
            }

            var disableIl2CppCoreDiag = (bool)(Debug.GetDiagnosticSwitch("VMIl2CppDisableNetCore") ?? false);

            if (disableIl2CppCoreDiag)
            {
                return(false);
            }

            bool shouldUse = false;

            if (Application.platform == RuntimePlatform.OSXEditor)
            {
                // On OSX 10.8 (and mabybe older versions, not sure) running .NET Core will result in the following error :
                //          dyld: lazy symbol binding failed: Symbol not found: __sincos_stret
                //
                // I'm not sure exactly what the issue is, but based on some google searching it's an issue not unique to .NET Core
                // and it does not happen in 10.9 and later.
                //
                // Some of our graphics tests run on OSX 10.8 and some users may have 10.8, in order to keep 10.8 working
                // we will fallback to running il2cpp on mono.
                // And as a precaution, let's use il2cpp on mono for anything older than 10.8 as well
                if (SystemInfo.operatingSystem.StartsWith("Mac OS X 10."))
                {
                    var versionText = SystemInfo.operatingSystem.Substring(9);
                    var version     = new Version(versionText);

                    if (version >= new Version(10, 9))
                    {
                        shouldUse = true;
                    }
                }
                else
                {
                    shouldUse = true;
                }
            }

            return(shouldUse && NetCoreProgram.IsNetCoreAvailable());
        }
コード例 #3
0
        private bool ShouldUseIl2CppCore()
        {
            if (!m_PlatformProvider.supportsUsingIl2cppCore)
            {
                return(false);
            }

            var disableIl2CppCoreEnv = System.Environment.GetEnvironmentVariable("UNITY_IL2CPP_DISABLE_NET_CORE");

            if (disableIl2CppCoreEnv == "1")
            {
                return(false);
            }

            var disableIl2CppCoreDiag = (bool)(Debug.GetDiagnosticSwitch("VMIl2CppDisableNetCore") ?? false);

            if (disableIl2CppCoreDiag)
            {
                return(false);
            }

            bool shouldUse = false;

            if (Application.platform == RuntimePlatform.OSXEditor)
            {
                // .Net Core 2.1 is only supported on MacOSX versions 10.12 and later
                if (SystemInfo.operatingSystem.StartsWith("Mac OS X 10."))
                {
                    var versionText = SystemInfo.operatingSystem.Substring(9);
                    var version     = new Version(versionText);

                    if (version >= new Version(10, 12))
                    {
                        shouldUse = true;
                    }
                }
                else
                {
                    shouldUse = true;
                }
            }

            return(shouldUse && NetCoreProgram.IsNetCoreAvailable());
        }
コード例 #4
0
        internal static string GetIl2CppFolder()
        {
            var pathOverride = System.Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");

            if (!string.IsNullOrEmpty(pathOverride))
            {
                return(pathOverride);
            }

            pathOverride = Debug.GetDiagnosticSwitch("VMIl2CppPath") as string;
            if (!string.IsNullOrEmpty(pathOverride))
            {
                return(pathOverride);
            }

            return(Path.GetFullPath(Path.Combine(
                                        EditorApplication.applicationContentsPath,
                                        "il2cpp")));
        }
コード例 #5
0
        private static void ProcessInitializeOnLoadMethodAttributes()
        {
            bool reportTimes = (bool)Debug.GetDiagnosticSwitch("EnableDomainReloadTimings").value;

            foreach (var method in TypeCache.GetMethodsWithAttribute <InitializeOnLoadMethodAttribute>())
            {
                using (new EditorPerformanceMarker($"InitializeOnLoad {method.DeclaringType?.Name}.{method.Name}", method.DeclaringType).Auto())
                    using (_profilerMarkerProcessInitializeOnLoadMethodAttributes.Auto(reportTimes, () => $"{method.DeclaringType?.FullName}::{method.Name}"))
                    {
                        try
                        {
                            method.Invoke(null, null);
                        }
                        catch (Exception x)
                        {
                            Debug.LogError(x);
                        }
                    }
            }
        }
コード例 #6
0
        static string GetIl2CppFolder(out bool isDevelopmentLocation)
        {
            var pathOverride = System.Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");

            if (!string.IsNullOrEmpty(pathOverride))
            {
                isDevelopmentLocation = true;
                return(pathOverride);
            }

            pathOverride = Debug.GetDiagnosticSwitch("VMIl2CppPath").value as string;
            if (!string.IsNullOrEmpty(pathOverride))
            {
                isDevelopmentLocation = true;
                return(pathOverride);
            }

            isDevelopmentLocation = false;
            return(Path.GetFullPath(Path.Combine(
                                        EditorApplication.applicationContentsPath,
                                        "il2cpp")));
        }
コード例 #7
0
        internal static string GetAdditionalArguments()
        {
            var arguments      = new List <string>();
            var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs();

            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            additionalArgs = System.Environment.GetEnvironmentVariable("IL2CPP_ADDITIONAL_ARGS");
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            additionalArgs = Debug.GetDiagnosticSwitch("VMIl2CppAdditionalArgs") as string;
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            return(arguments.Aggregate(String.Empty, (current, arg) => current + arg + " "));
        }
コード例 #8
0
        private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, string outputFolder, string workingDirectory, out string output, out string error, string linkerPath, IIl2CppPlatformProvider platformProvider, IEnumerable <string> additionalBlacklist, BuildTargetGroup buildTargetGroup, ManagedStrippingLevel managedStrippingLevel)
        {
            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            additionalBlacklist = additionalBlacklist.Select(s => Path.IsPathRooted(s) ? s : Path.Combine(workingDirectory, s)).Where(File.Exists);

            var userBlackLists = GetUserBlacklistFiles();

            foreach (var ub in userBlackLists)
            {
                Console.WriteLine("UserBlackList: " + ub);
            }

            additionalBlacklist = additionalBlacklist.Concat(userBlackLists);

            var args = new List <string>
            {
                "-out=\"" + outputFolder + "\"",
                "-x=\"" + GetModuleWhitelist("Core", platformProvider.moduleStrippingInformationFolder) + "\"",
            };

            args.AddRange(additionalBlacklist.Select(path => "-x \"" + path + "\""));

            args.AddRange(searchDirs.Select(d => "-d \"" + d + "\""));
            args.AddRange(assemblies.Select(assembly => "--include-unity-root-assembly=\"" + Path.GetFullPath(assembly) + "\""));
            args.Add($"--dotnetruntime={GetRuntimeArgumentValueForLinker(buildTargetGroup)}");
            args.Add($"--dotnetprofile={GetProfileArgumentValueForLinker(buildTargetGroup)}");
            args.Add("--use-editor-options");
            args.Add($"--include-directory={CommandLineFormatter.PrepareFileName(workingDirectory)}");

            if (EditorUserBuildSettings.allowDebugging)
            {
                args.Add("--editor-settings-flag=AllowDebugging");
            }

            if (EditorUserBuildSettings.development)
            {
                args.Add("--editor-settings-flag=Development");
            }

            args.Add($"--rule-set={GetRuleSetForStrippingLevel(managedStrippingLevel)}");

            // One final check to make sure we only run high on latest runtime.
            if ((managedStrippingLevel == ManagedStrippingLevel.High) && (PlayerSettingsEditor.IsLatestApiCompatibility(PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup))))
            {
                // Prepare the arguments to run the UnityLinker.  When in high mode, need to also
                // supply the IL2CPP compiler platform and compiler architecture.  When the scripting backend
                // is not IL2CPP, we have to map those strings and use a utility function to figure out proper strings.

                // Currently only need to do this on the non aot platforms of Android, Windows, Mac, Linux.
                var compilerPlatform     = "";
                var compilerArchitecture = "";
                Il2CppNativeCodeBuilder il2cppNativeCodeBuilder = platformProvider.CreateIl2CppNativeCodeBuilder();
                if (il2cppNativeCodeBuilder != null)
                {
                    compilerPlatform     = il2cppNativeCodeBuilder.CompilerPlatform;
                    compilerArchitecture = il2cppNativeCodeBuilder.CompilerArchitecture;
                }
                else
                {
                    GetUnityLinkerPlatformStringsFromBuildTarget(platformProvider.target, out compilerPlatform, out compilerArchitecture);
                }

                args.Add($"--platform={compilerPlatform}");
                if (platformProvider.target != BuildTarget.Android)
                {
                    args.Add($"--architecture={compilerArchitecture}");
                }
            }

            var additionalArgs = System.Environment.GetEnvironmentVariable("UNITYLINKER_ADDITIONAL_ARGS");

            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs);
            }

            additionalArgs = Debug.GetDiagnosticSwitch("VMUnityLinkerAdditionalArgs") as string;
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs.Trim('\''));
            }

            return(RunAssemblyLinker(args, out output, out error, linkerPath, workingDirectory));
        }
コード例 #9
0
        private static bool StripAssembliesTo(string outputFolder, out string output, out string error, IEnumerable <string> linkXmlFiles, UnityLinkerRunInformation runInformation)
        {
            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            var assemblies = runInformation.AssembliesToProcess();

            var args = new List <string>
            {
                $"-out={CommandLineFormatter.PrepareFileName(outputFolder)}",
            };

            if (!UseUnityLinkerEngineModuleStripping)
            {
                args.Add($"-x={CommandLineFormatter.PrepareFileName(GetModuleWhitelist("Core", runInformation.platformProvider.moduleStrippingInformationFolder))}");
            }

            args.AddRange(linkXmlFiles.Select(path => $"-x={CommandLineFormatter.PrepareFileName(path)}"));
            args.AddRange(runInformation.SearchDirectories.Select(d => $"-d={CommandLineFormatter.PrepareFileName(d)}"));
            args.AddRange(assemblies.Select(assembly => $"--include-unity-root-assembly={CommandLineFormatter.PrepareFileName(Path.GetFullPath(assembly))}"));
            args.Add($"--dotnetruntime={runInformation.argumentProvider.Runtime}");
            args.Add($"--dotnetprofile={runInformation.argumentProvider.Profile}");
            args.Add("--use-editor-options");
            args.Add($"--include-directory={CommandLineFormatter.PrepareFileName(runInformation.managedAssemblyFolderPath)}");

            if (EditorUserBuildSettings.allowDebugging)
            {
                args.Add("--editor-settings-flag=AllowDebugging");
            }

            if (EditorUserBuildSettings.development)
            {
                args.Add("--editor-settings-flag=Development");
            }

            args.Add($"--rule-set={runInformation.argumentProvider.RuleSet}");
            args.Add($"--editor-data-file={CommandLineFormatter.PrepareFileName(runInformation.EditorToLinkerDataPath)}");

            if (runInformation.platformProvider.AllowOutputToBeMadePlatformDependent)
            {
                var platform = runInformation.platformProvider.Platform;
                if (string.IsNullOrEmpty(platform))
                {
                    throw new ArgumentException($"Platform is required if AllowOutputToBeMadePlatformDependent is true");
                }

                args.Add($"--platform={platform}");
            }

            if (runInformation.platformProvider.AllowOutputToBeMadeArchitectureDependent)
            {
                var architecture = runInformation.platformProvider.Architecture;
                if (string.IsNullOrEmpty(architecture))
                {
                    throw new ArgumentException($"Architecture is required if AllowOutputToBeMadeArchitectureDependent is true");
                }
                args.Add($"--architecture={architecture}");
            }

            if (!UseUnityLinkerEngineModuleStripping)
            {
                args.Add("--disable-engine-module-support");
            }

            if (runInformation.performEngineStripping)
            {
                args.Add("--enable-engine-module-stripping");

                if (UnityEngine.Connect.UnityConnectSettings.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableUnityConnect");
                }

                if (UnityEngine.Analytics.PerformanceReporting.enabled)
                {
                    args.Add("--engine-stripping-flag=EnablePerformanceReporting");
                }

                if (UnityEngine.Analytics.Analytics.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableAnalytics");
                }

                if (UnityEditor.CrashReporting.CrashReportingSettings.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableCrashReporting");
                }

                if (UnityEditorInternal.VR.VRModule.ShouldInjectVRDependenciesForBuildTarget(runInformation.target))
                {
                    args.Add("--engine-stripping-flag=EnableVR");
                }
            }

            var modulesAssetPath = runInformation.ModulesAssetFilePath;

            if (File.Exists(modulesAssetPath))
            {
                args.Add($"--engine-modules-asset-file={CommandLineFormatter.PrepareFileName(modulesAssetPath)}");
            }

            var additionalArgs = System.Environment.GetEnvironmentVariable("UNITYLINKER_ADDITIONAL_ARGS");

            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs);
            }

            additionalArgs = Debug.GetDiagnosticSwitch("VMUnityLinkerAdditionalArgs") as string;
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs.Trim('\''));
            }

            return(RunAssemblyLinker(args, out output, out error, UnityLinkerPath, runInformation.managedAssemblyFolderPath));
        }
コード例 #10
0
        private void ConvertPlayerDlltoCpp(string inputDirectory, string outputDirectory, string workingDirectory, bool platformSupportsManagedDebugging)
        {
            var arguments = new List <string>();

            arguments.Add("--convert-to-cpp");

            if (m_PlatformProvider.emitNullChecks)
            {
                arguments.Add("--emit-null-checks");
            }

            if (m_PlatformProvider.enableStackTraces)
            {
                arguments.Add("--enable-stacktrace");
            }

            if (m_PlatformProvider.enableArrayBoundsCheck)
            {
                arguments.Add("--enable-array-bounds-check");
            }

            if (m_PlatformProvider.enableDivideByZeroCheck)
            {
                arguments.Add("--enable-divide-by-zero-check");
            }

            if (m_BuildForMonoRuntime)
            {
                arguments.Add("--mono-runtime");
            }

            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target);

            arguments.Add(string.Format("--dotnetprofile=\"{0}\"", IL2CPPUtils.ApiCompatibilityLevelToDotNetProfileArgument(PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup))));

            if (IL2CPPUtils.EnableIL2CPPDebugger(m_PlatformProvider, buildTargetGroup) && platformSupportsManagedDebugging)
            {
                arguments.Add("--enable-debugger");
            }

            var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder();

            if (il2CppNativeCodeBuilder != null)
            {
                var compilerConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(buildTargetGroup);
                Il2CppNativeCodeBuilderUtils.ClearAndPrepareCacheDirectory(il2CppNativeCodeBuilder);
                arguments.AddRange(Il2CppNativeCodeBuilderUtils.AddBuilderArguments(il2CppNativeCodeBuilder, OutputFileRelativePath(), m_PlatformProvider.includePaths, m_PlatformProvider.libraryPaths, compilerConfiguration));
            }

            arguments.Add(string.Format("--map-file-parser=\"{0}\"", GetMapFileParserPath()));

            var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs();

            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            additionalArgs = System.Environment.GetEnvironmentVariable("IL2CPP_ADDITIONAL_ARGS");
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            additionalArgs = Debug.GetDiagnosticSwitch("VMIl2CppAdditionalArgs") as string;
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                arguments.Add(additionalArgs);
            }

            arguments.Add("--directory=\"" + Path.GetFullPath(inputDirectory) + "\"");

            arguments.Add(string.Format("--generatedcppdir=\"{0}\"", Path.GetFullPath(outputDirectory)));

            string progressMessage = "Converting managed assemblies to C++";

            if (il2CppNativeCodeBuilder != null)
            {
                progressMessage = "Building native binary with IL2CPP...";
            }

            if (EditorUtility.DisplayCancelableProgressBar("Building Player", progressMessage, 0.3f))
            {
                throw new OperationCanceledException();
            }

            Action <ProcessStartInfo> setupStartInfo = null;

            if (il2CppNativeCodeBuilder != null)
            {
                setupStartInfo = il2CppNativeCodeBuilder.SetupStartInfo;
            }

            if (PlayerBuildInterface.ExtraTypesProvider != null)
            {
                var extraTypes = new HashSet <string>();
                foreach (var extraType in PlayerBuildInterface.ExtraTypesProvider())
                {
                    extraTypes.Add(extraType);
                }

                var tempFile = Path.GetFullPath(Path.Combine(m_TempFolder, "extra-types.txt"));
                File.WriteAllLines(tempFile, extraTypes.ToArray());
                arguments.Add(string.Format("--extra-types-file=\"{0}\"", tempFile));
            }

            RunIl2CppWithArguments(arguments, setupStartInfo, workingDirectory);
        }
コード例 #11
0
        private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, string outputFolder, string workingDirectory, out string output, out string error, string linkerPath, IIl2CppPlatformProvider platformProvider, IEnumerable <string> additionalBlacklist, BuildTargetGroup buildTargetGroup, ManagedStrippingLevel managedStrippingLevel, bool stripEngineCode, string editorToLinkerDataPath)
        {
            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            additionalBlacklist = additionalBlacklist.Select(s => Path.IsPathRooted(s) ? s : Path.Combine(workingDirectory, s)).Where(File.Exists);

            var userBlackLists = GetUserBlacklistFiles();

            foreach (var ub in userBlackLists)
            {
                Console.WriteLine("UserBlackList: " + ub);
            }

            additionalBlacklist = additionalBlacklist.Concat(userBlackLists);

            var args = new List <string>
            {
                $"-out={CommandLineFormatter.PrepareFileName(outputFolder)}",
            };

            if (!UseUnityLinkerEngineModuleStripping)
            {
                args.Add($"-x={CommandLineFormatter.PrepareFileName(GetModuleWhitelist("Core", platformProvider.moduleStrippingInformationFolder))}");
            }

            args.AddRange(additionalBlacklist.Select(path => $"-x={CommandLineFormatter.PrepareFileName(path)}"));

            args.AddRange(searchDirs.Select(d => $"-d={CommandLineFormatter.PrepareFileName(d)}"));
            args.AddRange(assemblies.Select(assembly => $"--include-unity-root-assembly={CommandLineFormatter.PrepareFileName(Path.GetFullPath(assembly))}"));
            args.Add($"--dotnetruntime={GetRuntimeArgumentValueForLinker(buildTargetGroup)}");
            args.Add($"--dotnetprofile={GetProfileArgumentValueForLinker(buildTargetGroup)}");
            args.Add("--use-editor-options");
            args.Add($"--include-directory={CommandLineFormatter.PrepareFileName(workingDirectory)}");

            if (EditorUserBuildSettings.allowDebugging)
            {
                args.Add("--editor-settings-flag=AllowDebugging");
            }

            if (EditorUserBuildSettings.development)
            {
                args.Add("--editor-settings-flag=Development");
            }

            args.Add($"--rule-set={GetRuleSetForStrippingLevel(managedStrippingLevel)}");
            args.Add($"--editor-data-file={CommandLineFormatter.PrepareFileName(editorToLinkerDataPath)}");

            var compilerPlatform     = "";
            var compilerArchitecture = "";
            Il2CppNativeCodeBuilder il2cppNativeCodeBuilder = platformProvider.CreateIl2CppNativeCodeBuilder();

            if (il2cppNativeCodeBuilder != null)
            {
                compilerPlatform     = il2cppNativeCodeBuilder.CompilerPlatform;
                compilerArchitecture = il2cppNativeCodeBuilder.CompilerArchitecture;
            }
            else
            {
                // When the scripting backend is not IL2CPP, we have to map those strings and use a utility function to figure out proper strings.
                GetUnityLinkerPlatformStringsFromBuildTarget(platformProvider.target, out compilerPlatform, out compilerArchitecture);
            }

            args.Add($"--platform={compilerPlatform}");
            if (!string.IsNullOrEmpty(compilerArchitecture))
            {
                args.Add($"--architecture={compilerArchitecture}");
            }

            if (!UseUnityLinkerEngineModuleStripping)
            {
                args.Add("--disable-engine-module-support");
            }

            if (stripEngineCode)
            {
                args.Add("--enable-engine-module-stripping");

                if (UnityEngine.Connect.UnityConnectSettings.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableUnityConnect");
                }

                if (UnityEngine.Analytics.PerformanceReporting.enabled)
                {
                    args.Add("--engine-stripping-flag=EnablePerformanceReporting");
                }

                if (UnityEngine.Analytics.Analytics.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableAnalytics");
                }

                if (UnityEditor.CrashReporting.CrashReportingSettings.enabled)
                {
                    args.Add("--engine-stripping-flag=EnableCrashReporting");
                }

                if (UnityEditorInternal.VR.VRModule.ShouldInjectVRDependenciesForBuildTarget(platformProvider.target))
                {
                    args.Add("--engine-stripping-flag=EnableVR");
                }
            }

            var modulesAssetPath = Path.Combine(platformProvider.moduleStrippingInformationFolder, "../modules.asset");

            if (File.Exists(modulesAssetPath))
            {
                args.Add($"--engine-modules-asset-file={CommandLineFormatter.PrepareFileName(modulesAssetPath)}");
            }

            var additionalArgs = System.Environment.GetEnvironmentVariable("UNITYLINKER_ADDITIONAL_ARGS");

            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs);
            }

            additionalArgs = Debug.GetDiagnosticSwitch("VMUnityLinkerAdditionalArgs") as string;
            if (!string.IsNullOrEmpty(additionalArgs))
            {
                args.Add(additionalArgs.Trim('\''));
            }

            return(RunAssemblyLinker(args, out output, out error, linkerPath, workingDirectory));
        }