Thursday, March 3, 2011

Debugging GPCP with Visual Studio

Back in the early days of Visual Studio.NET the IDE shipped with a program called DbgCLR, which was found in a GuiDebug directory in the VS distribution.  Since VS-2008, this program is not present.

When run with the default /debug option GPCP emits a "pdb" file for use by the VS debugger. However, since there is no language integration of current versions of Component Pascal into VS debugging CP programs with the VS debugger requires some ingenuity.  This blog deals with how I do it.  It is entirely possible that there are other ways of achieving the same effect, like the man said "your mileage may vary".

The key idea is to trick VS into thinking that you are debugging a C# project, which just happens to jump out into other language modules. In this case we will tell VS that the aim of the project is to compile the runtime support file RTS.cs to produce RTS.dll.

Simple Example, Debugging Hello World

(1) We begin by creating a directory, called DebugHello, say, and place in the directory our source file Hello.cp and the runtime system source RTS.cs. The runtime file is found under
C:\gpcp-CLR\source\libs\CSharp
in my installation.
(2) Start up Visual Studio and select File > New > Project from Existing Code. When the wizard starts, choose Visual C# as the project type,and click Next.
(3) At the next  screen of the wizard we point VS at the directory that was created at step(1), choose a name for the project, DebugHello, and set the output type as Class Library. Click Finish.
(4) At this stage we go into the Solution Explorer pane, right click on DebugHello, and select Properties. In the Properties page choose the Applications tab, and set the Assembly name to "RTS". Probably nothing else needs to be set in this tab. We will assume that the default output path bin\debug is left unchanged in the Build tab.
(5) In the Build Events tab we want to create a pre-build event to compile Hello.cp. We could do this with a simple command line call to gpcp, but for multi-source-file compilations we need to control the place where the symbol and output files go so we will use the command
call $(ProjectDir)PreBuild.bat $(ProjectDir)
The content of this batch file is discussed later. Once we have the batch file we can invoke Build > Build Solution. The bin\debug directory will now contain RTS.dll, RTS.pdb, Hello.exe, Hello.pdb.
(6) In the Debug tab we select the Start external program radio button, and use the file browser to select the Hello.exe executable in the output directory. This is all that is required for "Hello World", However for programs that take input we will also need to set the working directory and the command line arguments in this tab.
We may now open hello.cp in the Solution Explorer pane, place a breakpoint at BEGIN and start debugging!

The PreBuild.bat File

We want to set the working directory so that the symbol file, IL file and list file (if any) are placed in the source directory.  However, we want the output files to go to the bin\debug directory. The source directory is passed as an argument to the batch file by the macro $(ProjectDir) so the batch file reads --
cd %1%
gpcp /bindir=bin\debug hello.cp

A Bigger Example - Debugging GPCP

A (much) larger example would be debugging GPCP itself. This example illustrates a number of extra issues typical of larger programs. Here are the steps equivalent to those of the simple example.

(1) We begin by creating a directory, called DebugGpcp, say, and place in the directory our source file runtime system source RTS.cs. As well, we copy ALL of the cp sources from the source\gpcp directory of the distribution.
(2) Start up Visual Studio and select File > New > Project from Existing Code. When the wizard starts, choose Visual C# as the project type,and click Next.
(3) At the next  screen of the wizard we point VS at the directory that was created at step(1), choose a name for the project, DebugGpcp, and set the output type as Class Library. Click Finish.
(4) At this stage we go into the Solution Explorer pane, right click on DebugGpcp, and select Properties. In the Properties page choose the Applications tab, and set the Assembly name to "RTS". Probably nothing else needs to be set in this tab. We will assume that the default output path bin\debug is left unchanged in the Build tab.
(5) In the Build Events tab we want to create a pre-build event to compile gpcp using the command
call $(ProjectDir)PreBuild.bat $(ProjectDir)
The content of this batch file is discussed later. Once we have the batch file we can invoke Build > Build Solution. The bin\debug directory will now contain RTS.dll, RTS.pdb and lots of other files.
(6) In the Debug tab we select the Start external program radio button, and use the file browser to select the gpcp.exe executable in the output directory. We also set the working directory and the command line arguments to compile the source file that we want GPCP to compile.

The PreBuild.bat File for GPCP

For a project as large as gpcp we want to only compile the files that have been modified, so we will use the CPMake tool here. CPMake compiles only changed files, or those that depend on changed files, and also compiles all the sources in the dependence order. If a complete recompile is wanted the /all option of CPMake does this. Our required batch file is --

cd %1%
CPMake /bindir=bin\debug gpcp
Note that the argument to CPMake is the base name of the program, without file extension.

Extra Libraries

GPCP requires a number of additional libraries, as well as RTS. All of these dynamic link libraries need to be copied into the bin\debug directory in order for the program to work. Here are the libraries that GPCP relies on. Some are standard libraries in the distribution, others are components of GPCP that are implemented in C#.

GPBinFiles.dll
GPFiles.dll
GPTextFiles.dll
MsilAsm.dll
QUT.PERWAPI.dll
QUT.SymbolRW.dll

If we want to step into these libraries it is necessary to copy the corresponding pdb files as well. Since these libraries should remain unchanged during any debugging of GPCP, these files are not checked for recompilation during the debugging process.

And that is all there is to it.

Happy debugging!

No comments:

Post a Comment