From 811d6395736bd9a31d34a37cfb046070ddce3f2a Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 29 Sep 2023 22:07:45 +0300 Subject: [PATCH 1/4] Generate Visual Studio Code build tasks for C#-projects --- .../VisualStudioCodeProjectGenerator.cs | 222 +++++++++--------- 1 file changed, 109 insertions(+), 113 deletions(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index fdf1df4e2..2fdff6fa4 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -155,122 +155,118 @@ namespace Flax.Build.Projects.VisualStudioCode { foreach (var project in solution.Projects) { - // C++ project - if (project.Type == TargetType.NativeCpp) + if (project.Name == "BuildScripts") + continue; + + bool defaultTask = project == solution.MainProject; + foreach (var configuration in project.Configurations) { - bool defaultTask = project == solution.MainProject; - foreach (var configuration in project.Configurations) + var target = configuration.Target; + var name = project.Name + '|' + configuration.Name; + + json.BeginObject(); + + json.AddField("label", name); + + bool isDefaultTask = defaultTask && configuration.Configuration == TargetConfiguration.Development && configuration.Platform == Platform.BuildPlatform.Target; + + json.BeginObject("group"); { - var target = configuration.Target; - var name = project.Name + '|' + configuration.Name; - - json.BeginObject(); - - json.AddField("label", name); - - if (defaultTask && configuration.Configuration == TargetConfiguration.Development && configuration.Platform == Platform.BuildPlatform.Target) - { - defaultTask = false; - json.BeginObject("group"); - { - json.AddField("kind", "build"); - json.AddField("isDefault", true); - } - json.EndObject(); - } - else - { - json.AddField("group", "build"); - } - - switch (Platform.BuildPlatform.Target) - { - case TargetPlatform.Windows: - { - json.AddField("command", buildToolPath); - json.BeginArray("args"); - { - json.AddUnnamedField("-build"); - json.AddUnnamedField("-log"); - json.AddUnnamedField("-mutex"); - json.AddUnnamedField(string.Format("\\\"-workspace={0}\\\"", buildToolWorkspace)); - json.AddUnnamedField(string.Format("-arch={0}", configuration.ArchitectureName)); - json.AddUnnamedField(string.Format("-configuration={0}", configuration.ConfigurationName)); - json.AddUnnamedField(string.Format("-platform={0}", configuration.PlatformName)); - json.AddUnnamedField(string.Format("-buildTargets={0}", target.Name)); - if (!string.IsNullOrEmpty(Configuration.Compiler)) - json.AddUnnamedField(string.Format("-compiler={0}", Configuration.Compiler)); - } - json.EndArray(); - - json.AddField("type", "shell"); - - json.BeginObject("options"); - { - json.AddField("cwd", buildToolWorkspace); - } - json.EndObject(); - break; - } - case TargetPlatform.Linux: - { - json.AddField("command", buildToolPath); - json.BeginArray("args"); - { - json.AddUnnamedField("--build"); - json.AddUnnamedField("--log"); - json.AddUnnamedField("--mutex"); - json.AddUnnamedField(string.Format("--workspace=\\\"{0}\\\"", buildToolWorkspace)); - json.AddUnnamedField(string.Format("--arch={0}", configuration.Architecture)); - json.AddUnnamedField(string.Format("--configuration={0}", configuration.ConfigurationName)); - json.AddUnnamedField(string.Format("--platform={0}", configuration.PlatformName)); - json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name)); - if (!string.IsNullOrEmpty(Configuration.Compiler)) - json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler)); - } - json.EndArray(); - - json.AddField("type", "shell"); - - json.BeginObject("options"); - { - json.AddField("cwd", buildToolWorkspace); - } - json.EndObject(); - break; - } - case TargetPlatform.Mac: - { - json.AddField("command", buildToolPath); - json.BeginArray("args"); - { - json.AddUnnamedField("--build"); - json.AddUnnamedField("--log"); - json.AddUnnamedField("--mutex"); - json.AddUnnamedField(string.Format("--workspace=\\\"{0}\\\"", buildToolWorkspace)); - json.AddUnnamedField(string.Format("--arch={0}", configuration.Architecture)); - json.AddUnnamedField(string.Format("--configuration={0}", configuration.ConfigurationName)); - json.AddUnnamedField(string.Format("--platform={0}", configuration.PlatformName)); - json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name)); - if (!string.IsNullOrEmpty(Configuration.Compiler)) - json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler)); - } - json.EndArray(); - - json.AddField("type", "shell"); - - json.BeginObject("options"); - { - json.AddField("cwd", buildToolWorkspace); - } - json.EndObject(); - break; - } - default: throw new Exception("Visual Code project generator does not support current platform."); - } - - json.EndObject(); + json.AddField("kind", "build"); + json.AddField("isDefault", isDefaultTask); } + json.EndObject(); + + if (isDefaultTask) + defaultTask = false; + + switch (Platform.BuildPlatform.Target) + { + case TargetPlatform.Windows: + { + json.AddField("command", buildToolPath); + json.BeginArray("args"); + { + json.AddUnnamedField("-build"); + json.AddUnnamedField("-log"); + json.AddUnnamedField("-mutex"); + json.AddUnnamedField(string.Format("\\\"-workspace={0}\\\"", buildToolWorkspace)); + json.AddUnnamedField(string.Format("-arch={0}", configuration.ArchitectureName)); + json.AddUnnamedField(string.Format("-configuration={0}", configuration.ConfigurationName)); + json.AddUnnamedField(string.Format("-platform={0}", configuration.PlatformName)); + json.AddUnnamedField(string.Format("-buildTargets={0}", target.Name)); + if (!string.IsNullOrEmpty(Configuration.Compiler)) + json.AddUnnamedField(string.Format("-compiler={0}", Configuration.Compiler)); + } + json.EndArray(); + + json.AddField("type", "shell"); + + json.BeginObject("options"); + { + json.AddField("cwd", buildToolWorkspace); + } + json.EndObject(); + break; + } + case TargetPlatform.Linux: + { + json.AddField("command", buildToolPath); + json.BeginArray("args"); + { + json.AddUnnamedField("--build"); + json.AddUnnamedField("--log"); + json.AddUnnamedField("--mutex"); + json.AddUnnamedField(string.Format("--workspace=\\\"{0}\\\"", buildToolWorkspace)); + json.AddUnnamedField(string.Format("--arch={0}", configuration.Architecture)); + json.AddUnnamedField(string.Format("--configuration={0}", configuration.ConfigurationName)); + json.AddUnnamedField(string.Format("--platform={0}", configuration.PlatformName)); + json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name)); + if (!string.IsNullOrEmpty(Configuration.Compiler)) + json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler)); + } + json.EndArray(); + + json.AddField("type", "shell"); + + json.BeginObject("options"); + { + json.AddField("cwd", buildToolWorkspace); + } + json.EndObject(); + break; + } + case TargetPlatform.Mac: + { + json.AddField("command", buildToolPath); + json.BeginArray("args"); + { + json.AddUnnamedField("--build"); + json.AddUnnamedField("--log"); + json.AddUnnamedField("--mutex"); + json.AddUnnamedField(string.Format("--workspace=\\\"{0}\\\"", buildToolWorkspace)); + json.AddUnnamedField(string.Format("--arch={0}", configuration.Architecture)); + json.AddUnnamedField(string.Format("--configuration={0}", configuration.ConfigurationName)); + json.AddUnnamedField(string.Format("--platform={0}", configuration.PlatformName)); + json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name)); + if (!string.IsNullOrEmpty(Configuration.Compiler)) + json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler)); + } + json.EndArray(); + + json.AddField("type", "shell"); + + json.BeginObject("options"); + { + json.AddField("cwd", buildToolWorkspace); + } + json.EndObject(); + break; + } + default: throw new Exception("Visual Code project generator does not support current platform."); + } + + json.EndObject(); } } } From 8a19b5ddd6c4754a6ca45be7b4a20a52cb31bc9a Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 29 Sep 2023 23:46:57 +0300 Subject: [PATCH 2/4] Skip adding VSCode task and launch profiles for plugins and dependencies --- .../VisualStudioCodeProjectGenerator.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 2fdff6fa4..743a643f3 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -158,6 +158,10 @@ namespace Flax.Build.Projects.VisualStudioCode if (project.Name == "BuildScripts") continue; + // Skip duplicate build tasks + if (project.Name == "FlaxEngine" || (solution.MainProject.Name != "Flax" && solution.MainProject != project)) + continue; + bool defaultTask = project == solution.MainProject; foreach (var configuration in project.Configurations) { @@ -288,9 +292,15 @@ namespace Flax.Build.Projects.VisualStudioCode { foreach (var project in solution.Projects) { + if (project.Name == "BuildScripts") + continue; // C++ project if (project.Type == TargetType.NativeCpp) { + // Skip generating launch profiles for plugins and dependencies + if (solution.MainProject.Name != "Flax" && project.Name != "Flax.Build" && solution.MainProject.WorkspaceRootPath != project.WorkspaceRootPath) + continue; + foreach (var configuration in project.Configurations) { var name = project.Name + '|' + configuration.Name; From bf2c10b036a484705add7e3b8b0a7409eb67df69 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 29 Sep 2023 23:50:15 +0300 Subject: [PATCH 3/4] Generate one VSCode debugger attach launch profile per debugger type --- .../VisualStudioCodeProjectGenerator.cs | 238 +++++++++--------- 1 file changed, 115 insertions(+), 123 deletions(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 743a643f3..f1f7e415e 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -281,6 +281,9 @@ namespace Flax.Build.Projects.VisualStudioCode json.Save(Path.Combine(vsCodeFolder, "tasks.json")); } + bool hasMonoProjects = solution.Projects.Any(x => x.Type == TargetType.DotNet); + bool hasDotnetProjects = solution.Projects.Any(x => x.Type == TargetType.DotNetCore); + // Create launch file using (var json = new JsonWriter()) { @@ -320,115 +323,49 @@ namespace Flax.Build.Projects.VisualStudioCode json.AddField("preLaunchTask", name); json.AddField("cwd", buildToolWorkspace); - switch (Platform.BuildPlatform.Target) + WriteNativePlatformLaunchSettings(json, configuration.Platform); + + if (outputType != TargetOutputType.Executable && configuration.Name.StartsWith("Editor.")) { - case TargetPlatform.Windows: - if (configuration.Platform == TargetPlatform.Windows && outputType != TargetOutputType.Executable && configuration.Name.StartsWith("Editor.")) + if (configuration.Platform == TargetPlatform.Windows) { var editorFolder = configuration.Architecture == TargetArchitecture.x64 ? "Win64" : "Win32"; json.AddField("program", Path.Combine(Globals.EngineRoot, "Binaries", "Editor", editorFolder, configuration.ConfigurationName, "FlaxEditor.exe")); - json.BeginArray("args"); + } + else if (configuration.Platform == TargetPlatform.Linux) + json.AddField("program", Path.Combine(Globals.EngineRoot, "Binaries", "Editor", "Linux", configuration.ConfigurationName, "FlaxEditor")); + else if (configuration.Platform == TargetPlatform.Mac) + json.AddField("program", Path.Combine(Globals.EngineRoot, "Binaries", "Editor", "Mac", configuration.ConfigurationName, "FlaxEditor")); + + json.BeginArray("args"); + { + json.AddUnnamedField("-project"); + json.AddUnnamedField(buildToolWorkspace); + json.AddUnnamedField("-skipCompile"); + if (hasMonoProjects) { - json.AddUnnamedField("-project"); - json.AddUnnamedField(buildToolWorkspace); - json.AddUnnamedField("-skipCompile"); json.AddUnnamedField("-debug"); json.AddUnnamedField("127.0.0.1:55555"); } - json.EndArray(); } - else - { - json.AddField("program", outputTargetFilePath); - } - break; - case TargetPlatform.Linux: - if (configuration.Platform == TargetPlatform.Linux && (outputType != TargetOutputType.Executable || project.BaseName == "Flax") && configuration.Name.StartsWith("Editor.")) - { - json.AddField("program", Path.Combine(Globals.EngineRoot, "Binaries", "Editor", "Linux", configuration.ConfigurationName, "FlaxEditor")); - } - else - { - json.AddField("program", outputTargetFilePath); - } - if (configuration.Platform == TargetPlatform.Linux) - { - json.AddField("MIMode", "gdb"); - json.BeginArray("setupCommands"); - { - json.BeginObject(); - json.AddField("description", "Enable pretty-printing for gdb"); - json.AddField("text", "-enable-pretty-printing"); - json.AddField("ignoreFailures", true); - json.EndObject(); - - // Ignore signals used by C# runtime - json.BeginObject(); - json.AddField("description", "ignore SIG34 signal"); - json.AddField("text", "handle SIG34 nostop noprint pass"); - json.EndObject(); - json.BeginObject(); - json.AddField("description", "ignore SIG35 signal"); - json.AddField("text", "handle SIG35 nostop noprint pass"); - json.EndObject(); - json.BeginObject(); - json.AddField("description", "ignore SIG36 signal"); - json.AddField("text", "handle SIG36 nostop noprint pass"); - json.EndObject(); - json.BeginObject(); - json.AddField("description", "ignore SIG357 signal"); - json.AddField("text", "handle SIG37 nostop noprint pass"); - json.EndObject(); - } - json.EndArray(); - json.BeginArray("args"); - { - json.AddUnnamedField("--std"); - if (outputType != TargetOutputType.Executable && configuration.Name.StartsWith("Editor.")) - { - json.AddUnnamedField("--project"); - json.AddUnnamedField(buildToolWorkspace); - json.AddUnnamedField("--skipCompile"); - } - } - json.EndArray(); - } - break; - case TargetPlatform.Mac: - if (configuration.Platform == TargetPlatform.Mac && (outputType != TargetOutputType.Executable || project.BaseName == "Flax") && configuration.Name.StartsWith("Editor.")) - { - json.AddField("program", Path.Combine(Globals.EngineRoot, "Binaries", "Editor", "Mac", configuration.ConfigurationName, "FlaxEditor")); - } - else - { - json.AddField("program", outputTargetFilePath); - } - if (configuration.Platform == TargetPlatform.Mac) - { - json.AddField("MIMode", "lldb"); - json.BeginArray("args"); - { - json.AddUnnamedField("--std"); - if (outputType != TargetOutputType.Executable && configuration.Name.StartsWith("Editor.")) - { - json.AddUnnamedField("--project"); - json.AddUnnamedField(buildToolWorkspace); - json.AddUnnamedField("--skipCompile"); - } - } - json.EndArray(); - } - break; + json.EndArray(); } - switch (configuration.Platform) + else { - case TargetPlatform.Windows: - json.AddField("stopAtEntry", false); - json.AddField("externalConsole", true); - break; - case TargetPlatform.Linux: - break; + json.AddField("program", outputTargetFilePath); + json.BeginArray("args"); + { + if (configuration.Platform == TargetPlatform.Linux || configuration.Platform == TargetPlatform.Mac) + json.AddUnnamedField("--std"); + if (hasMonoProjects) + { + json.AddUnnamedField("-debug"); + json.AddUnnamedField("127.0.0.1:55555"); + } + } + json.EndArray(); } + json.AddField("visualizerFile", Path.Combine(Globals.EngineRoot, "Source", "flax.natvis")); } json.EndObject(); @@ -437,16 +374,9 @@ namespace Flax.Build.Projects.VisualStudioCode // C# project else if (project.Type == TargetType.DotNetCore) { - // TODO: Skip generating launch profiles for plugins and dependencies - - json.BeginObject(); - { - json.AddField("type", "coreclr"); - json.AddField("name", project.Name + " (C# attach Editor)"); - json.AddField("request", "attach"); - json.AddField("processName", "FlaxEditor"); - } - json.EndObject(); + // Skip generating launch profiles for plugins and dependencies + if (solution.MainProject.WorkspaceRootPath != project.WorkspaceRootPath) + continue; foreach (var configuration in project.Configurations) { @@ -490,24 +420,33 @@ namespace Flax.Build.Projects.VisualStudioCode json.EndObject(); } } - // Mono C# project - else if (project.Type == TargetType.DotNet) - { - foreach (var configuration in project.Configurations) - { - json.BeginObject(); - { - json.AddField("type", "mono"); - json.AddField("name", project.Name + " (C# attach)" + '|' + configuration.Name); - json.AddField("request", "attach"); - json.AddField("address", "localhost"); - json.AddField("port", 55555); - } - json.EndObject(); - } - } } } + + if (hasDotnetProjects) + { + json.BeginObject(); + { + json.AddField("type", "coreclr"); + json.AddField("name", solution.Name + " (C# Attach Editor)"); + json.AddField("request", "attach"); + json.AddField("processName", "FlaxEditor"); + } + json.EndObject(); + } + if (hasMonoProjects) + { + json.BeginObject(); + { + json.AddField("type", "mono"); + json.AddField("name", solution.Name + " (C# Attach)"); + json.AddField("request", "attach"); + json.AddField("address", "localhost"); + json.AddField("port", 55555); + } + json.EndObject(); + } + json.EndArray(); } json.EndRootObject(); @@ -515,6 +454,59 @@ namespace Flax.Build.Projects.VisualStudioCode json.Save(Path.Combine(vsCodeFolder, "launch.json")); } + static void WriteNativePlatformLaunchSettings(JsonWriter json, TargetPlatform platform) + { + switch (Platform.BuildPlatform.Target) + { + case TargetPlatform.Linux: + if (platform == TargetPlatform.Linux) + { + json.AddField("MIMode", "gdb"); + json.BeginArray("setupCommands"); + { + json.BeginObject(); + json.AddField("description", "Enable pretty-printing for gdb"); + json.AddField("text", "-enable-pretty-printing"); + json.AddField("ignoreFailures", true); + json.EndObject(); + + // Ignore signals used by C# runtime + json.BeginObject(); + json.AddField("description", "ignore SIG34 signal"); + json.AddField("text", "handle SIG34 nostop noprint pass"); + json.EndObject(); + json.BeginObject(); + json.AddField("description", "ignore SIG35 signal"); + json.AddField("text", "handle SIG35 nostop noprint pass"); + json.EndObject(); + json.BeginObject(); + json.AddField("description", "ignore SIG36 signal"); + json.AddField("text", "handle SIG36 nostop noprint pass"); + json.EndObject(); + json.BeginObject(); + json.AddField("description", "ignore SIG357 signal"); + json.AddField("text", "handle SIG37 nostop noprint pass"); + json.EndObject(); + } + json.EndArray(); + } + break; + case TargetPlatform.Mac: + if (platform == TargetPlatform.Mac) + { + json.AddField("MIMode", "lldb"); + } + break; + } + switch (platform) + { + case TargetPlatform.Windows: + json.AddField("stopAtEntry", false); + json.AddField("externalConsole", true); + break; + } + } + // Create C++ properties file using (var json = new JsonWriter()) { From 8b8970e4b96527d4b363feef89fc0cc441b36cb2 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 29 Sep 2023 23:50:50 +0300 Subject: [PATCH 4/4] Generate VSCode attach profile for native debugging --- .../VisualStudioCodeProjectGenerator.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index f1f7e415e..887197258 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -281,6 +281,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.Save(Path.Combine(vsCodeFolder, "tasks.json")); } + bool hasNativeProjects = solution.Projects.Any(x => x.Type == TargetType.NativeCpp); bool hasMonoProjects = solution.Projects.Any(x => x.Type == TargetType.DotNet); bool hasDotnetProjects = solution.Projects.Any(x => x.Type == TargetType.DotNetCore); @@ -423,6 +424,27 @@ namespace Flax.Build.Projects.VisualStudioCode } } + if (hasNativeProjects) + { + foreach (var platform in solution.Projects.SelectMany(x => x.Configurations).Select(x => x.Platform).Distinct()) + { + json.BeginObject(); + { + if (platform == TargetPlatform.Windows) + json.AddField("type", "cppvsdbg"); + else + json.AddField("type", "cppdbg"); + json.AddField("name", solution.Name + " (Attach Editor)"); + json.AddField("request", "attach"); + json.AddField("processId", "${command:pickProcess}"); // Does not seem to be possible to attach by process name? + + WriteNativePlatformLaunchSettings(json, platform); + + json.AddField("visualizerFile", Path.Combine(Globals.EngineRoot, "Source", "flax.natvis")); + } + json.EndObject(); + } + } if (hasDotnetProjects) { json.BeginObject();