[Dexter] Add option to pass a Visual Studio solution instead of a binary
This patch allows a visual studio solution file to be passed directly into Dexter, instead of using a pre-built binary and a small internal solution file with template arguments. This is primarily to allow launching an application that has specific launch configuration requirements, without needing all the details of this configuration to be built directly into Dexter or adding a config file that simply duplicates existing settings in the VS solution. Reviewed By: Orlando Differential Revision: https://reviews.llvm.org/D110167
This commit is contained in:
parent
f94c9af622
commit
75b316929a
|
@ -48,6 +48,8 @@ def add_builder_tool_arguments(parser):
|
|||
type=str,
|
||||
choices=sorted(_find_build_scripts().keys()),
|
||||
help='test builder to use')
|
||||
build_group.add_argument('--vs-solution', metavar="<file>",
|
||||
help='provide a path to an already existing visual studio solution.')
|
||||
parser.add_argument(
|
||||
'--cflags', type=str, default='', help='compiler flags')
|
||||
parser.add_argument('--ldflags', type=str, default='', help='linker flags')
|
||||
|
|
|
@ -16,7 +16,6 @@ from types import SimpleNamespace
|
|||
from dex.command.CommandBase import StepExpectInfo
|
||||
from dex.dextIR import DebuggerIR, FrameIR, LocIR, StepIR, ValueIR
|
||||
from dex.utils.Exceptions import DebuggerException
|
||||
from dex.utils.Exceptions import NotYetLoadedDebuggerException
|
||||
from dex.utils.ReturnCode import ReturnCode
|
||||
|
||||
def watch_is_active(watch_info: StepExpectInfo, path, frame_idx, line_no):
|
||||
|
@ -44,11 +43,10 @@ class DebuggerBase(object, metaclass=abc.ABCMeta):
|
|||
|
||||
self._interface = None
|
||||
self.has_loaded = False
|
||||
self._loading_error = NotYetLoadedDebuggerException()
|
||||
self._loading_error = None
|
||||
try:
|
||||
self._interface = self._load_interface()
|
||||
self.has_loaded = True
|
||||
self._loading_error = None
|
||||
except DebuggerException:
|
||||
self._loading_error = sys.exc_info()
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ class DebuggerControllerBase(object, metaclass=abc.ABCMeta):
|
|||
"""
|
||||
self.debugger = debugger
|
||||
with self.debugger:
|
||||
self._run_debugger_custom()
|
||||
if not self.debugger.loading_error:
|
||||
self._run_debugger_custom()
|
||||
|
||||
# We may need to pickle this debugger controller after running the
|
||||
# debugger. Debuggers are not picklable objects, so set to None.
|
||||
self.debugger = None
|
||||
|
|
|
@ -67,6 +67,23 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst
|
|||
|
||||
super(VisualStudio, self).__init__(*args)
|
||||
|
||||
def _create_solution(self):
|
||||
self._solution.Create(self.context.working_directory.path,
|
||||
'DexterSolution')
|
||||
try:
|
||||
self._solution.AddFromFile(self._project_file)
|
||||
except OSError:
|
||||
raise LoadDebuggerException(
|
||||
'could not debug the specified executable', sys.exc_info())
|
||||
|
||||
def _load_solution(self):
|
||||
try:
|
||||
self._solution.Open(self.context.options.vs_solution)
|
||||
except:
|
||||
raise LoadDebuggerException(
|
||||
'could not load specified vs solution at {}'.
|
||||
format(self.context.options.vs_solution), sys.exc_info())
|
||||
|
||||
def _custom_init(self):
|
||||
try:
|
||||
self._debugger = self._interface.Debugger
|
||||
|
@ -76,14 +93,10 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst
|
|||
self.context.options.show_debugger)
|
||||
|
||||
self._solution = self._interface.Solution
|
||||
self._solution.Create(self.context.working_directory.path,
|
||||
'DexterSolution')
|
||||
|
||||
try:
|
||||
self._solution.AddFromFile(self._project_file)
|
||||
except OSError:
|
||||
raise LoadDebuggerException(
|
||||
'could not debug the specified executable', sys.exc_info())
|
||||
if self.context.options.vs_solution is None:
|
||||
self._create_solution()
|
||||
else:
|
||||
self._load_solution()
|
||||
|
||||
self._fn_step = self._debugger.StepInto
|
||||
self._fn_go = self._debugger.Go
|
||||
|
|
|
@ -58,7 +58,12 @@ class TestToolBase(ToolBase):
|
|||
warn(self.context, '--cflags and --ldflags will be ignored when not'
|
||||
' using --builder')
|
||||
|
||||
if options.binary:
|
||||
if options.vs_solution:
|
||||
options.vs_solution = os.path.abspath(options.vs_solution)
|
||||
if not os.path.isfile(options.vs_solution):
|
||||
raise Error('<d>could not find VS solution file</> <r>"{}"</>'
|
||||
.format(options.vs_solution))
|
||||
elif options.binary:
|
||||
options.binary = os.path.abspath(options.binary)
|
||||
if not os.path.isfile(options.binary):
|
||||
raise Error('<d>could not find binary file</> <r>"{}"</>'
|
||||
|
|
|
@ -42,20 +42,26 @@ class Tool(ToolBase):
|
|||
self.options = self.context.options
|
||||
Timer.display = self.options.time_report
|
||||
|
||||
def raise_debugger_error(self, action, debugger):
|
||||
msg = '<d>could not {} {}</> ({})\n'.format(
|
||||
action, debugger.name, debugger.loading_error)
|
||||
if self.options.verbose:
|
||||
msg = '{}\n {}'.format(
|
||||
msg, ' '.join(debugger.loading_error_trace))
|
||||
raise Error(msg)
|
||||
|
||||
def go(self) -> ReturnCode:
|
||||
with Timer('loading debugger'):
|
||||
debugger = Debuggers(self.context).load(self.options.debugger)
|
||||
|
||||
with Timer('running debugger'):
|
||||
if not debugger.is_available:
|
||||
msg = '<d>could not load {}</> ({})\n'.format(
|
||||
debugger.name, debugger.loading_error)
|
||||
if self.options.verbose:
|
||||
msg = '{}\n {}'.format(
|
||||
msg, ' '.join(debugger.loading_error_trace))
|
||||
raise Error(msg)
|
||||
self.raise_debugger_error('load', debugger)
|
||||
|
||||
self.debugger_controller.run_debugger(debugger)
|
||||
self.debugger_controller.run_debugger(debugger)
|
||||
|
||||
if debugger.loading_error:
|
||||
self.raise_debugger_error('run', debugger)
|
||||
|
||||
with open(self.controller_path, 'wb') as fp:
|
||||
pickle.dump(self.debugger_controller, fp)
|
||||
|
|
|
@ -108,9 +108,13 @@ class Tool(TestToolBase):
|
|||
"""Build an executable from the test source with the given --builder
|
||||
script and flags (--cflags, --ldflags) in the working directory.
|
||||
Or, if the --binary option has been given, copy the executable provided
|
||||
into the working directory and rename it to match the --builder output.
|
||||
into the working directory and rename it to match the --builder output
|
||||
or skip if --vs-solution was passed on the command line.
|
||||
"""
|
||||
|
||||
if self.context.options.vs_solution:
|
||||
return
|
||||
|
||||
options = self.context.options
|
||||
if options.binary:
|
||||
# Copy user's binary into the tmp working directory
|
||||
|
|
Loading…
Reference in New Issue