public override SourceFile AllocSourceFile(FileReference InitFilePath, DirectoryReference InitProjectSubFolder) { if (InitFilePath.GetFileName().StartsWith(".")) { return(null); } return(new EddieSourceFile(InitFilePath, InitProjectSubFolder)); }
UProjectInfo(FileReference InFilePath, bool bInIsCodeProject) { GameName = InFilePath.GetFileNameWithoutExtension(); FileName = InFilePath.GetFileName(); FilePath = InFilePath; Folder = FilePath.Directory; bIsCodeProject = bInIsCodeProject; }
/// <summary> /// Replaces a hot reload suffix in a filename. /// </summary> public static FileReference ReplaceSuffix(FileReference File, int Suffix) { string FileName = File.GetFileName(); // Find the end of the target and module name int HyphenIdx = FileName.IndexOf('-'); if (HyphenIdx == -1) { throw new BuildException("Hot-reloadable files are expected to contain a hyphen, eg. UE4Editor-Core"); } int NameEndIdx = HyphenIdx + 1; while (NameEndIdx < FileName.Length && FileName[NameEndIdx] != '.' && FileName[NameEndIdx] != '-') { NameEndIdx++; } // Strip any existing suffix if (NameEndIdx + 1 < FileName.Length && Char.IsDigit(FileName[NameEndIdx + 1])) { int SuffixEndIdx = NameEndIdx + 2; while (SuffixEndIdx < FileName.Length && Char.IsDigit(FileName[SuffixEndIdx])) { SuffixEndIdx++; } if (SuffixEndIdx == FileName.Length || FileName[SuffixEndIdx] == '-' || FileName[SuffixEndIdx] == '.') { FileName = FileName.Substring(0, NameEndIdx) + FileName.Substring(SuffixEndIdx); } } string NewFileName = String.Format("{0}-{1:D4}{2}", FileName.Substring(0, NameEndIdx), Suffix, FileName.Substring(NameEndIdx)); return(FileReference.Combine(File.Directory, NewFileName)); }
/// <summary> /// Execute the command /// </summary> /// <param name="Arguments">List of command line arguments</param> /// <returns>Always zero, or throws an exception</returns> public override int Execute(CommandLineArguments Arguments) { Arguments.ApplyTo(this); Arguments.CheckAllArgumentsUsed(); Log.TraceInformation("{0}", OutputFile.GetFileName()); // Read the input files string[] InputFileLines = FileReference.ReadAllLines(InputFileList); FileReference[] InputFiles = InputFileLines.Select(x => x.Trim()).Where(x => x.Length > 0).Select(x => new FileReference(x)).ToArray(); // Create the combined output file, and print the diagnostics to the log HashSet <string> UniqueItems = new HashSet <string>(); using (StreamWriter RawWriter = new StreamWriter(OutputFile.FullName)) { foreach (FileReference InputFile in InputFiles) { string[] Lines = File.ReadAllLines(InputFile.FullName); for (int LineIdx = 0; LineIdx < Lines.Length; LineIdx++) { string Line = Lines[LineIdx]; if (!String.IsNullOrWhiteSpace(Line) && UniqueItems.Add(Line)) { bool bCanParse = false; string[] Tokens = Line.Split(new string[] { "<#~>" }, StringSplitOptions.None); if (Tokens.Length >= 9) { //string Trial = Tokens[1]; string LineNumberStr = Tokens[2]; string FileName = Tokens[3]; string WarningCode = Tokens[5]; string WarningMessage = Tokens[6]; string FalseAlarmStr = Tokens[7]; string LevelStr = Tokens[8]; int LineNumber; bool bFalseAlarm; int Level; if (int.TryParse(LineNumberStr, out LineNumber) && bool.TryParse(FalseAlarmStr, out bFalseAlarm) && int.TryParse(LevelStr, out Level)) { bCanParse = true; // Ignore anything in ThirdParty folders if (FileName.Replace('/', '\\').IndexOf("\\ThirdParty\\", StringComparison.InvariantCultureIgnoreCase) == -1) { // Output the line to the raw output file RawWriter.WriteLine(Line); // Output the line to the log if (!bFalseAlarm && Level == 1) { Log.WriteLine(LogEventType.Warning, LogFormatOptions.NoSeverityPrefix, "{0}({1}): warning {2}: {3}", FileName, LineNumber, WarningCode, WarningMessage); } } } } if (!bCanParse) { Log.WriteLine(LogEventType.Warning, LogFormatOptions.NoSeverityPrefix, "{0}({1}): warning: Unable to parse PVS output line '{2}' (tokens=|{3}|)", InputFile, LineIdx + 1, Line, String.Join("|", Tokens)); } } } } } Log.TraceInformation("Written {0} {1} to {2}.", UniqueItems.Count, (UniqueItems.Count == 1)? "diagnostic" : "diagnostics", OutputFile.FullName); return(0); }
/// <summary> /// Writes a manifest containing all the information needed to create a live coding patch /// </summary> /// <param name="ManifestFile">File to write to</param> /// <param name="Actions">List of actions that are part of the graph</param> /// <param name="OriginalFileToPatchedFile">Map of original object files to patched object files</param> public static void WriteLiveCodingManifest(FileReference ManifestFile, List <Action> Actions, Dictionary <FileReference, FileReference> OriginalFileToPatchedFile) { // Find all the output object files HashSet <FileItem> ObjectFiles = new HashSet <FileItem>(); foreach (Action Action in Actions) { if (Action.ActionType == ActionType.Compile) { ObjectFiles.UnionWith(Action.ProducedItems.Where(x => x.HasExtension(".obj"))); } } // Write the output manifest using (JsonWriter Writer = new JsonWriter(ManifestFile)) { Writer.WriteObjectStart(); Action LinkAction = Actions.FirstOrDefault(x => x.ActionType == ActionType.Link && x.ProducedItems.Any(y => y.HasExtension(".exe") || y.HasExtension(".dll"))); if (LinkAction != null) { FileReference LinkerPath = LinkAction.CommandPath; if (String.Compare(LinkerPath.GetFileName(), "link-filter.exe", StringComparison.OrdinalIgnoreCase) == 0) { string[] Arguments = CommandLineArguments.Split(LinkAction.CommandArguments); for (int Idx = 0; Idx + 1 < Arguments.Length; Idx++) { if (Arguments[Idx] == "--") { LinkerPath = new FileReference(Arguments[Idx + 1]); break; } } } Writer.WriteValue("LinkerPath", LinkerPath.FullName); } Writer.WriteObjectStart("LinkerEnvironment"); foreach (System.Collections.DictionaryEntry Entry in Environment.GetEnvironmentVariables()) { Writer.WriteValue(Entry.Key.ToString(), Entry.Value.ToString()); } Writer.WriteObjectEnd(); Writer.WriteArrayStart("Modules"); foreach (Action Action in Actions) { if (Action.ActionType == ActionType.Link) { FileItem OutputFile = Action.ProducedItems.FirstOrDefault(x => x.HasExtension(".exe") || x.HasExtension(".dll")); if (OutputFile != null && Action.PrerequisiteItems.Any(x => OriginalFileToPatchedFile.ContainsKey(x.Location))) { Writer.WriteObjectStart(); Writer.WriteValue("Output", OutputFile.Location.FullName); Writer.WriteArrayStart("Inputs"); foreach (FileItem InputFile in Action.PrerequisiteItems) { FileReference PatchedFile; if (OriginalFileToPatchedFile.TryGetValue(InputFile.Location, out PatchedFile)) { Writer.WriteValue(PatchedFile.FullName); } } Writer.WriteArrayEnd(); Writer.WriteObjectEnd(); } } } Writer.WriteArrayEnd(); Writer.WriteObjectEnd(); } }
/// <summary> /// Creates all the modules required for this target /// </summary> /// <param name="CreateModule">Delegate to create a module with a given name</param> /// <param name="ReferenceChain">Chain of references before reaching this module</param> public void RecursivelyCreateModules(CreateModuleDelegate CreateModule, string ReferenceChain) { // Get the reference chain for anything referenced by this module string NextReferenceChain = String.Format("{0} -> {1}", ReferenceChain, (RulesFile == null)? Name : RulesFile.GetFileName()); // Recursively create all the public include path modules. These modules may not be added to the target (and we don't process their referenced // dependencies), but they need to be created to set up their include paths. RecursivelyCreateIncludePathModulesByName(Rules.PublicIncludePathModuleNames, ref PublicIncludePathModules, CreateModule, NextReferenceChain); // Create all the referenced modules. This path can be recursive, so we check against PrivateIncludePathModules to ensure we don't recurse through the // same module twice (it produces better errors if something fails). if (PrivateIncludePathModules == null) { // Create the private include path modules RecursivelyCreateIncludePathModulesByName(Rules.PrivateIncludePathModuleNames, ref PrivateIncludePathModules, CreateModule, NextReferenceChain); // Create all the dependency modules RecursivelyCreateModulesByName(Rules.PublicDependencyModuleNames, ref PublicDependencyModules, CreateModule, NextReferenceChain); RecursivelyCreateModulesByName(Rules.PrivateDependencyModuleNames, ref PrivateDependencyModules, CreateModule, NextReferenceChain); RecursivelyCreateModulesByName(Rules.DynamicallyLoadedModuleNames, ref DynamicallyLoadedModules, CreateModule, NextReferenceChain); RecursivelyCreateModulesByName(Rules.PlatformSpecificDynamicallyLoadedModuleNames, ref PlatformSpecificDynamicallyLoadedModules, CreateModule, NextReferenceChain); } }
/// <summary> /// Dynamically compiles an assembly for the specified source file and loads that assembly into the application's /// current domain. If an assembly has already been compiled and is not out of date, then it will be loaded and /// no compilation is necessary. /// </summary> /// <param name="OutputAssemblyPath">Full path to the assembly to be created</param> /// <param name="SourceFileNames">List of source file name</param> /// <param name="ReferencedAssembies"></param> /// <param name="PreprocessorDefines"></param> /// <param name="DoNotCompile"></param> /// <param name="TreatWarningsAsErrors"></param> /// <returns>The assembly that was loaded</returns> public static Assembly CompileAndLoadAssembly(FileReference OutputAssemblyPath, HashSet <FileReference> SourceFileNames, List <string> ReferencedAssembies = null, List <string> PreprocessorDefines = null, bool DoNotCompile = false, bool TreatWarningsAsErrors = false) { // Check to see if the resulting assembly is compiled and up to date FileReference AssemblyManifestFilePath = FileReference.Combine(OutputAssemblyPath.Directory, Path.GetFileNameWithoutExtension(OutputAssemblyPath.FullName) + "Manifest.json"); bool bNeedsCompilation = false; if (!DoNotCompile) { bNeedsCompilation = RequiresCompilation(SourceFileNames, AssemblyManifestFilePath, OutputAssemblyPath); } // Load the assembly to ensure it is correct Assembly CompiledAssembly = null; if (!bNeedsCompilation) { try { // Load the previously-compiled assembly from disk CompiledAssembly = Assembly.LoadFile(OutputAssemblyPath.FullName); } catch (FileLoadException Ex) { Log.TraceInformation(String.Format("Unable to load the previously-compiled assembly file '{0}'. Unreal Build Tool will try to recompile this assembly now. (Exception: {1})", OutputAssemblyPath, Ex.Message)); bNeedsCompilation = true; } catch (BadImageFormatException Ex) { Log.TraceInformation(String.Format("Compiled assembly file '{0}' appears to be for a newer CLR version or is otherwise invalid. Unreal Build Tool will try to recompile this assembly now. (Exception: {1})", OutputAssemblyPath, Ex.Message)); bNeedsCompilation = true; } catch (FileNotFoundException) { throw new BuildException("Precompiled rules assembly '{0}' does not exist.", OutputAssemblyPath); } catch (Exception Ex) { throw new BuildException(Ex, "Error while loading previously-compiled assembly file '{0}'. (Exception: {1})", OutputAssemblyPath, Ex.Message); } } // Compile the assembly if me if (bNeedsCompilation) { using (Timeline.ScopeEvent(String.Format("Compiling rules assembly ({0})", OutputAssemblyPath.GetFileName()))) { CompiledAssembly = CompileAssembly(OutputAssemblyPath, SourceFileNames, ReferencedAssembies, PreprocessorDefines, TreatWarningsAsErrors); } using (JsonWriter Writer = new JsonWriter(AssemblyManifestFilePath)) { ReadOnlyBuildVersion Version = ReadOnlyBuildVersion.Current; Writer.WriteObjectStart(); // Save out a list of all the source files we compiled. This is so that we can tell if whole files were added or removed // since the previous time we compiled the assembly. In that case, we'll always want to recompile it! Writer.WriteStringArrayField("SourceFiles", SourceFileNames.Select(x => x.FullName)); Writer.WriteValue("EngineVersion", FormatVersionNumber(Version)); Writer.WriteObjectEnd(); } } #if !NET_CORE // Load the assembly into our app domain try { AppDomain.CurrentDomain.Load(CompiledAssembly.GetName()); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to load the compiled build assembly '{0}' into our application's domain. (Exception: {1})", OutputAssemblyPath, Ex.Message); } #endif return(CompiledAssembly); }
/// <summary> /// Return any custom paths for VisualStudio this platform requires /// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath. /// </summary> /// <param name="InPlatform">The UnrealTargetPlatform being built</param> /// <param name="InConfiguration">The configuration being built</param> /// <param name="TargetType">The type of target (game or program)</param> /// <param name="TargetRulesPath">Path to the target.cs file</param> /// <param name="ProjectFilePath">Path to the project file</param> /// <param name="NMakeOutputPath"></param> /// <param name="InProjectFileFormat">Format for the generated project files</param> /// <param name="ProjectFileBuilder">The project file content</param> /// <returns>The custom path lines for the project file; Empty string if it doesn't require one</returns> public override void GetVisualStudioPathsEntries(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { base.GetVisualStudioPathsEntries(InPlatform, InConfiguration, TargetType, TargetRulesPath, ProjectFilePath, NMakeOutputPath, InProjectFileFormat, ProjectFileBuilder); if (IsVSLuminSupportInstalled(InProjectFileFormat) && TargetType == TargetType.Game && InPlatform == UnrealTargetPlatform.Lumin) { string MLSDK = Utils.CleanDirectorySeparators(Environment.GetEnvironmentVariable("MLSDK"), '\\'); // TODO: Check if MPK name can be other than the project name. string GameName = TargetRulesPath.GetFileNameWithoutExtension(); GameName = Path.GetFileNameWithoutExtension(GameName); string PackageFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); string PackageName = GameName; if (InConfiguration != UnrealTargetConfiguration.Development) { PackageName = GameName + "-" + InPlatform.ToString() + "-" + InConfiguration.ToString(); } PackageFile = Path.Combine(PackageFile, PackageName + ".mpk"); // Can't use $(NMakeOutput) directly since that is defined after <ELFFile> tag and thus ends up being translated as an empty string. string ELFFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); // Provide path to stripped executable so all symbols are resolved from the external sym file instead. ELFFile = Path.Combine(ELFFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", GetElfName(NMakeOutputPath)); string DebuggerFlavor = "MLDebugger"; string SymFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); SymFile = Path.Combine(SymFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", Path.ChangeExtension(NMakeOutputPath.GetFileName(), ".sym")); // following are defaults for debugger options string Attach = "false"; string EnableAutoStop = "true"; string AutoStopAtFunction = "main"; string EnablePrettyPrinting = "true"; string MLDownloadOnStart = "true"; string CustomPathEntriesTemplate = "<MLSDK>{0}</MLSDK>" + ProjectFileGenerator.NewLine + "<PackageFile>{1}</PackageFile>" + ProjectFileGenerator.NewLine + "<ELFFile>{2}</ELFFile>" + ProjectFileGenerator.NewLine + "<DebuggerFlavor>{3}</DebuggerFlavor>" + ProjectFileGenerator.NewLine + "<Attach>{4}</Attach>" + ProjectFileGenerator.NewLine + "<EnableAutoStop>{5}</EnableAutoStop>" + ProjectFileGenerator.NewLine + "<AutoStopAtFunction>{6}</AutoStopAtFunction>" + ProjectFileGenerator.NewLine + "<EnablePrettyPrinting>{7}</EnablePrettyPrinting>" + ProjectFileGenerator.NewLine + "<MLDownloadOnStart>{8}</MLDownloadOnStart>" + ProjectFileGenerator.NewLine; // No need to provide SymFile path. The file is automatically picked up when it resides in the same folder and has the same name as the ElfFile // "<SymFile>{9}</SymFile>" + ProjectFileGenerator.NewLine; ProjectFileBuilder.Append(ProjectFileGenerator.NewLine + string.Format(CustomPathEntriesTemplate, MLSDK, PackageFile, ELFFile, DebuggerFlavor, Attach, EnableAutoStop, AutoStopAtFunction, EnablePrettyPrinting, MLDownloadOnStart)); } }
/// <summary> /// For platforms that need to output multiple files per binary (ie Android "fat" binaries) /// this will emit multiple paths. By default, it simply makes an array from the input /// </summary> public override List <FileReference> FinalizeBinaryPaths(FileReference BinaryName, FileReference ProjectFile, ReadOnlyTargetRules Target) { List <FileReference> BinaryPaths = new List <FileReference>(); if (Target.bIsBuildingConsoleApplication || !String.IsNullOrEmpty(BinaryName.GetExtension())) { BinaryPaths.Add(BinaryName); } else { BinaryPaths.Add(new FileReference(BinaryName.FullName + ".app/Contents/MacOS/" + BinaryName.GetFileName())); } return(BinaryPaths); }
private void WriteLaunchFile() { JsonFile OutFile = new JsonFile(); EDebugMode DebugMode = (HostPlatform == UnrealTargetPlatform.Win64) ? EDebugMode.VS : EDebugMode.GDB; OutFile.BeginRootObject(); { OutFile.AddField("version", "0.2.0"); OutFile.BeginArray("configurations"); { List <ProjectFile> Projects = new List <ProjectFile>(GeneratedProjectFiles); Projects.Sort((A, B) => { return(A.ProjectFilePath.GetFileNameWithoutExtension().CompareTo(B.ProjectFilePath.GetFileNameWithoutExtension())); }); foreach (ProjectFile Project in AllProjectFiles) { if (Project.ProjectFilePath.GetExtension() == ProjectFileExtension) { foreach (ProjectTarget Target in Project.ProjectTargets) { List <UnrealTargetConfiguration> Configs = new List <UnrealTargetConfiguration>(); Target.TargetRules.GetSupportedConfigurations(ref Configs, true); foreach (UnrealTargetConfiguration Config in Configs) { if (SupportedConfigurations.Contains(Config)) { FileReference Executable = GetExecutableFilename(Project, Target, HostPlatform, Config); string Name = Target.TargetRules == null?Project.ProjectFilePath.GetFileNameWithoutExtension() : Target.TargetRules.Name; string LaunchTaskName = $"{Name} {HostPlatform} {Config} Build"; string ExecutableDirectory = "${workspaceRoot}/" + Executable.Directory.MakeRelativeTo(UnrealBuildTool.RootDirectory).ToString().Replace("\\", "/"); OutFile.BeginObject(); { OutFile.AddField("name", Target.TargetRules.Name + " (" + Config.ToString() + ")"); OutFile.AddField("request", "launch"); OutFile.AddField("preLaunchTask", LaunchTaskName); OutFile.AddField("program", ExecutableDirectory + "/" + Executable.GetFileName()); OutFile.BeginArray("args"); { } OutFile.EndArray(); OutFile.AddField("stopAtEntry", true); OutFile.AddField("cwd", ExecutableDirectory); OutFile.BeginArray("environment"); { } OutFile.EndArray(); OutFile.AddField("externalConsole", true); switch (DebugMode) { case EDebugMode.VS: { OutFile.AddField("type", "cppvsdbg"); break; } case EDebugMode.GDB: { OutFile.AddField("type", "cppdbg"); OutFile.AddField("MIMode", "lldb"); break; } } } OutFile.EndObject(); } } } } else if (Project.ProjectFilePath.GetExtension() == ".csproj") { /* * foreach (ProjectTarget Target in Project.ProjectTargets) * { * foreach (UnrealTargetConfiguration Config in Target.ExtraSupportedConfigurations) * { * string TaskName = $"{Project.ProjectFilePath.GetFileNameWithoutExtension()} ({Config})"; * string BuildTaskName = $"{Project.ProjectFilePath.GetFileNameWithoutExtension()} {HostPlatform} {Config} Build"; * FileReference Executable = GetExecutableFilename(Project, Target, HostPlatform, Config); * * OutFile.BeginObject(); * { * OutFile.AddField("name", TaskName); * OutFile.AddField("type", "coreclr"); * OutFile.AddField("request", "launch"); * OutFile.AddField("preLaunchTask", BuildTaskName); * OutFile.AddField("program", Executable.ToString()); * OutFile.BeginArray("args"); * { * * } * OutFile.EndArray(); * } * OutFile.EndObject(); * } * } */ } } } OutFile.EndArray(); } OutFile.EndRootObject(); OutFile.Write(FileReference.Combine(VSCodeDir, "launch.json")); }
/// <summary> /// Return any custom paths for VisualStudio this platform requires /// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath. /// </summary> /// <param name="InPlatform">The UnrealTargetPlatform being built</param> /// <param name="InConfiguration">The configuration being built</param> /// <param name="TargetType">The type of target (game or program)</param> /// <param name="TargetRulesPath">Path to the target.cs file</param> /// <param name="ProjectFilePath">Path to the project file</param> /// <param name="NMakeOutputPath"></param> /// <param name="InProjectFileFormat">Format for the generated project files</param> /// <param name="ProjectFileBuilder">The project file content</param> /// <returns>The custom path lines for the project file; Empty string if it doesn't require one</returns> public override void GetVisualStudioPathsEntries(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { base.GetVisualStudioPathsEntries(InPlatform, InConfiguration, TargetType, TargetRulesPath, ProjectFilePath, NMakeOutputPath, InProjectFileFormat, ProjectFileBuilder); if (IsVSLuminSupportInstalled(InProjectFileFormat) && TargetType == TargetType.Game && InPlatform == UnrealTargetPlatform.Lumin) { string MLSDK = Utils.CleanDirectorySeparators(Environment.GetEnvironmentVariable("MLSDK"), '\\'); // TODO: Check if MPK name can be other than the project name. string GameName = TargetRulesPath.GetFileNameWithoutExtension(); GameName = Path.GetFileNameWithoutExtension(GameName); string PackageFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); string PackageName = GameName; if (InConfiguration != UnrealTargetConfiguration.Development) { PackageName = GameName + "-" + InPlatform.ToString() + "-" + InConfiguration.ToString(); } PackageFile = Path.Combine(PackageFile, PackageName + ".mpk"); // TODO: Fix NMakeOutput to have the the correct architecture name and then set ELFFile to $(NMakeOutput) string ELFFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); ELFFile = Path.Combine(ELFFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Packaged\\bin\\" + GameName); string DebuggerFlavor = "MLDebugger"; string SymFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); SymFile = Path.Combine(SymFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", Path.ChangeExtension(NMakeOutputPath.GetFileName(), ".sym")); // following are defaults for debugger options string Attach = "false"; string EnableAutoStop = "true"; string AutoStopAtFunction = "main"; string EnablePrettyPrinting = "true"; string MLDownloadOnStart = "true"; string CustomPathEntriesTemplate = "<MLSDK>{0}</MLSDK>" + ProjectFileGenerator.NewLine + "<PackageFile>{1}</PackageFile>" + ProjectFileGenerator.NewLine + "<ELFFile>{2}</ELFFile>" + ProjectFileGenerator.NewLine + "<DebuggerFlavor>{3}</DebuggerFlavor>" + ProjectFileGenerator.NewLine + "<Attach>{4}</Attach>" + ProjectFileGenerator.NewLine + "<EnableAutoStop>{5}</EnableAutoStop>" + ProjectFileGenerator.NewLine + "<AutoStopAtFunction>{6}</AutoStopAtFunction>" + ProjectFileGenerator.NewLine + "<EnablePrettyPrinting>{7}</EnablePrettyPrinting>" + ProjectFileGenerator.NewLine + "<MLDownloadOnStart>{8}</MLDownloadOnStart>" + ProjectFileGenerator.NewLine + "<SymFile>{9}</SymFile>" + ProjectFileGenerator.NewLine; ProjectFileBuilder.Append(ProjectFileGenerator.NewLine + string.Format(CustomPathEntriesTemplate, MLSDK, PackageFile, ELFFile, DebuggerFlavor, Attach, EnableAutoStop, AutoStopAtFunction, EnablePrettyPrinting, MLDownloadOnStart, SymFile)); } }