Skip to content

Commit a23caaf

Browse files
committed
Add support for debugging under msvc toolchain and fix few omissions from the previous commit
1 parent dbd9eca commit a23caaf

File tree

6 files changed

+146
-60
lines changed

6 files changed

+146
-60
lines changed

VisualRust.Project/Launcher/GnuDebugLauncher.cs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,19 @@
1111
using System.Threading.Tasks;
1212
using System.Xml;
1313
using System.Xml.Serialization;
14+
using VisualRust.Shared;
1415

1516
namespace VisualRust.Project.Launcher
1617
{
1718
class GnuDebugLauncher : IRustProjectLauncher
1819
{
1920
readonly LauncherEnvironment env;
21+
readonly TargetTriple triple;
2022

21-
public GnuDebugLauncher(LauncherEnvironment env)
23+
public GnuDebugLauncher(LauncherEnvironment env, TargetTriple triple)
2224
{
2325
this.env = env;
26+
this.triple = triple;
2427
}
2528

2629
public void Launch(string path, string args, string workingDir)
@@ -43,7 +46,7 @@ private PipeLaunchOptions BuildLaunchOptions(string path, string args, string wo
4346
// We could go through LocalLaunchOptions, but this way we can pass additional args
4447
PipeLaunchOptions options = new PipeLaunchOptions();
4548
options.PipePath = GetGdbPath();
46-
options.PipeArguments = String.Format("-q -interpreter=mi {0}", env.GdbExtraArguments());
49+
options.PipeArguments = String.Format("-q -interpreter=mi {0}", GetExtraArguments());
4750
options.ExePath = EscapePath(path);
4851
options.ExeArguments = args;
4952
options.SetupCommands = GetSetupCommands();
@@ -86,23 +89,35 @@ private static string EscapePath(string path)
8689
Command[] GetSetupCommands()
8790
{
8891
return new string[] { "-gdb-set new-console on" }
89-
.Union(env.GdbScriptLines())
92+
.Union(GetScriptLines())
9093
.Select(cmd => new Command { Value = cmd })
9194
.ToArray();
9295
}
9396

9497
string GetGdbPath()
9598
{
96-
string gdbPath = env.GdbCustomPath();
99+
string gdbPath = GetCustomPath();
97100
if (gdbPath != null)
98101
return gdbPath;
99102
return Path.Combine(
100103
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
101104
"gdb",
102-
env.GetArchitectureName(),
105+
GetArchitectureName(),
103106
"bin\\gdb");
104107
}
105108

109+
private string GetArchitectureName()
110+
{
111+
if(triple != null)
112+
{
113+
if(triple.Arch == "i686" || triple.Arch == "x86_64")
114+
return triple.Arch;
115+
}
116+
if (System.Environment.Is64BitOperatingSystem)
117+
return "x86_64";
118+
return "i686";
119+
}
120+
106121
static string ToXmlString<T>(T obj)
107122
{
108123
var builder = new StringBuilder();
@@ -113,5 +128,26 @@ static string ToXmlString<T>(T obj)
113128
}
114129
return builder.ToString();
115130
}
131+
132+
string GetCustomPath()
133+
{
134+
bool useCustomPath = env.GetDebugConfigurationProperty<bool>("UseCustomGdbPath");
135+
if(!useCustomPath)
136+
return null;
137+
return env.GetDebugConfigurationProperty<string>("DebuggerLocation");
138+
}
139+
140+
string GetExtraArguments()
141+
{
142+
return env.GetDebugConfigurationProperty<string>("ExtraArgs");
143+
}
144+
145+
string[] GetScriptLines()
146+
{
147+
string debuggerScript = env.GetDebugConfigurationProperty<string>("DebuggerScript");
148+
if(String.IsNullOrEmpty(debuggerScript))
149+
return new string[0];
150+
return debuggerScript.Split(new [] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
151+
}
116152
}
117153
}

VisualRust.Project/Launcher/LauncherEnviroment.cs

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@
66
using System.Text;
77
using System.Threading.Tasks;
88
using Microsoft.VisualStudio.Shell.Interop;
9+
using System.Diagnostics;
10+
using System.Text.RegularExpressions;
11+
using VisualRust.Shared;
912

1013
namespace VisualRust.Project.Launcher
1114
{
1215
class LauncherEnvironment
1316
{
1417
readonly RustProjectNode project;
1518
readonly Configuration.Debug debugConfig;
19+
readonly RustProjectConfig projectConfig;
1620

17-
public LauncherEnvironment(RustProjectNode project, Configuration.Debug debugConfig)
21+
public LauncherEnvironment(RustProjectNode project, Configuration.Debug debugConfig, RustProjectConfig projConfig)
1822
{
1923
this.project = project;
2024
this.debugConfig = debugConfig;
25+
this.projectConfig = projConfig;
2126
}
2227

2328
public string GetRustInstallPath()
@@ -50,47 +55,62 @@ public void LaunchVsDebugger(VsDebugTargetInfo4 target)
5055
vsDebugger.LaunchDebugTargets4((uint)targets.Length, targets, results);
5156
}
5257

53-
public string GetStartupExecutable()
58+
public T GetDebugConfigurationProperty<T>(string key)
5459
{
55-
return Path.Combine(project.GetProjectProperty("TargetDir"), project.GetProjectProperty("TargetFileName"));
60+
var env = (EnvDTE.DTE)project.GetService(typeof(EnvDTE.DTE));
61+
return (T)env.Properties["Visual Rust", "Debugging"].Item(key).Value;
5662
}
5763

58-
public string GdbCustomPath()
64+
public string GetProjectProperty(string key)
5965
{
60-
bool useCustomPath = GetDebugProperty<bool>("UseCustomGdbPath");
61-
if(!useCustomPath)
62-
return null;
63-
return GetDebugProperty<string>("DebuggerLocation");
66+
return project.GetProjectProperty(key);
6467
}
6568

66-
public string GdbExtraArguments()
69+
public TargetTriple GetTargetTriple()
6770
{
68-
return GetDebugProperty<string>("ExtraArgs");
71+
TargetTriple confTriple = TryGetTripleFromConfiguration();
72+
if(confTriple != null)
73+
return confTriple;
74+
return TryGetTripleFromRustc();
6975
}
7076

71-
public string[] GdbScriptLines()
77+
public void ForceBuild()
7278
{
73-
if(String.IsNullOrEmpty(debugConfig.DebuggerScript))
74-
return new string[0];
75-
return debugConfig.DebuggerScript.Split(new [] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
79+
project.Build("Build");
7680
}
7781

78-
T GetDebugProperty<T>(string key)
82+
TargetTriple TryGetTripleFromConfiguration()
7983
{
80-
var env = (EnvDTE.DTE)project.GetService(typeof(EnvDTE.DTE));
81-
return (T)env.Properties["Visual Rust", "Debugging"].Item(key).Value;
84+
string triple = Configuration.Build.LoadFrom(new ProjectConfig[] { projectConfig }).PlatformTarget;
85+
return TargetTriple.Create(triple);
8286
}
8387

84-
public bool IsMsvcToolchain()
88+
TargetTriple TryGetTripleFromRustc()
8589
{
86-
return false;
90+
string defaultInstallPath = Shared.Environment.FindInstallPath("default");
91+
if(defaultInstallPath == null)
92+
return null;
93+
string rustcPath = Path.Combine(defaultInstallPath, "rustc.exe");
94+
string rustcHost = GetRustcHost(rustcPath);
95+
return TargetTriple.Create(rustcHost);
8796
}
8897

89-
public string GetArchitectureName()
98+
static string GetRustcHost(string exePath)
9099
{
91-
if (Environment.Is64BitOperatingSystem)
92-
return "x86_64";
93-
return "i686";
100+
ProcessStartInfo psi = new ProcessStartInfo
101+
{
102+
UseShellExecute = false,
103+
CreateNoWindow = true,
104+
FileName = exePath,
105+
RedirectStandardOutput = true,
106+
Arguments = "-Vv"
107+
};
108+
Process proc = Process.Start(psi);
109+
string verboseVersion = proc.StandardOutput.ReadToEnd();
110+
Match hostMatch = Regex.Match(verboseVersion, "^host:\\s*(.+)$", RegexOptions.Multiline);
111+
if (hostMatch.Groups.Count == 1)
112+
return null;
113+
return hostMatch.Groups[1].Value;
94114
}
95115
}
96116
}

VisualRust.Project/Launcher/MsvcDebugLauncher.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.VisualStudioTools.Project;
1+
using Microsoft.VisualStudio.Shell.Interop;
2+
using Microsoft.VisualStudioTools.Project;
23
using System;
34
using System.Collections.Generic;
45
using System.Linq;
@@ -9,9 +10,24 @@ namespace VisualRust.Project.Launcher
910
{
1011
class MsvcDebugLauncher : IRustProjectLauncher
1112
{
13+
readonly LauncherEnvironment env;
14+
15+
public MsvcDebugLauncher(LauncherEnvironment env)
16+
{
17+
this.env = env;
18+
}
19+
1220
public void Launch(string path, string args, string workingDir)
1321
{
14-
throw new NotImplementedException();
22+
VsDebugTargetInfo4 target = new VsDebugTargetInfo4
23+
{
24+
dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_CreateProcess,
25+
guidLaunchDebugEngine = Constants.NativeOnlyEngine,
26+
bstrExe = path,
27+
bstrArg = args,
28+
bstrCurDir = workingDir
29+
};
30+
env.LaunchVsDebugger(target);
1531
}
1632
}
1733
}

VisualRust.Project/RustProjectLauncher.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.VisualStudioTools;
1313
using Microsoft.VisualStudioTools.Project;
1414
using VisualRust.Project.Launcher;
15+
using VisualRust.Shared;
1516

1617
namespace VisualRust.Project
1718
{
@@ -31,38 +32,48 @@ public RustProjectLauncher(RustProjectNode project)
3132
{
3233
throw new InvalidOperationException("A project with an Output Type of Library cannot be started directly.");
3334
}
34-
this.environment = new LauncherEnvironment(project, debugConfig);
35+
this.environment = new LauncherEnvironment(project, debugConfig, projectConfig);
3536
}
3637

3738
public int LaunchProject(bool debug)
3839
{
3940
string startupFilePath;
4041
if (debugConfig.StartAction == Configuration.StartAction.Project)
41-
startupFilePath = environment.GetStartupExecutable();
42+
startupFilePath = GetStartupExecutable();
4243
else
4344
startupFilePath = debugConfig.ExternalProgram;
4445
return LaunchFile(startupFilePath, debug);
4546
}
4647

4748
public int LaunchFile(string file, bool debug)
4849
{
50+
if (debugConfig.StartAction == Configuration.StartAction.Project
51+
&& !File.Exists(file))
52+
{
53+
environment.ForceBuild();
54+
}
4955
IRustProjectLauncher launcher = ChooseLauncher(debug);
5056
launcher.Launch(
5157
file,
5258
debugConfig.CommandLineArgs,
5359
debugConfig.WorkingDir);
5460
return VSConstants.S_OK;
61+
}
5562

63+
string GetStartupExecutable()
64+
{
65+
return Path.Combine(environment.GetProjectProperty("TargetDir"), environment.GetProjectProperty("TargetFileName"));
5666
}
5767

5868
private IRustProjectLauncher ChooseLauncher(bool debug)
5969
{
6070
if(!debug)
6171
return new ReleaseLauncher(environment);
62-
if(environment.IsMsvcToolchain())
63-
return new MsvcDebugLauncher();
72+
TargetTriple triple = environment.GetTargetTriple();
73+
if(triple.Abi == "msvc")
74+
return new MsvcDebugLauncher(environment);
6475
else
65-
return new GnuDebugLauncher(environment);
76+
return new GnuDebugLauncher(environment, triple);
6677
}
6778
}
6879
}

0 commit comments

Comments
 (0)