Skip to content

Getting Started

Anthony Leonardo Gracio edited this page Aug 17, 2022 · 8 revisions

Using Ada in VS Code

In this tutorial, you will configure Visual Studio Code to use the GCC Ada compiler (gnat) and GDB debugger on Linux, Windows or Mac OS X. GCC stands for GNU Compiler Collection; GNAT is GNU Ada Translator in GCC; GPRbuild is a multi-language builder; GDB is the GNU debugger.

After configuring VS Code, you will compile and debug a simple Ada project in VS Code. This tutorial does not teach you GCC, GDB, Ubuntu or the Ada language. For those subjects, there are many good resources available on the Web.

If you have trouble, feel free to file an issue for this tutorial in the ada_language_server repository.

Prerequisites

To successfully complete this tutorial, you must do the following:

  • Install Visual Studio Code.

  • Install the Ada extension for VS Code. You can install the Ada extension by searching for 'adacore' in the Extensions view (Ctrl+Shift+X).

    Ada extension

  • Install the Native Debug extension (Optional). You can install it by searching for 'native debug' in the Extensions view (Ctrl+Shift+X). Note that this extension is now installed by default on newer versions of the extension.

Ensure GNAT is installed

Although you'll use VS Code to edit your source code, you'll compile the source code using the GNAT compiler. You'll also use GDB to debug and gprbuild to build aplications or libraries. These tools are not installed by default, so you have to install them. Fortunately, that's easy.

  • On Linux, install packages from the system repository

    sudo install gnat gprbuild gdb
    
  • On Windows, setup MSYS2 and then install mingw-w64-gcc-ada, mingw-w64-gprbuild, mingw-w64-gdb packages.

    pacman -S mingw-w64-gcc-ada mingw-w64-gprbuild mingw-w64-gdb
    
  • On Mac OS X, install GNAT GCC Mac OS X as described here

    installer -pkg gcc-11.1.0-x86_64-apple-darwin15.pkg
    export PATH=/opt/gcc-11.1.0/bin:$PATH
    

Create Hello World

From the terminal window, create an empty folder called projects to store your VS Code projects. Then create a subfolder called helloworld, navigate into it, and open VS Code in that folder by entering the following commands:

mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .

The code . command opens VS Code in the current working folder, which becomes your "workspace". As you go through the tutorial, you will create three files in a .vscode folder in the workspace:

  • tasks.json (compiler build settings)
  • launch.json (debugger settings)
  • settings.json (project file path and other settings)

Create a project file

The GNAT project file allows you to manage complex builds involving a number of source files, directories, and options for different system configurations. It's recomended to create a project file even for simplest Ada project.

In the File Explorer title bar, select New File and name the file hello_world.gpr.

New File button

Paste in the following source code:

project Hello_World is
   for Main use ("hello_world.adb");
   for Object_Dir use ".objs";

   package Compiler is
      for Default_Switches ("Ada") use ("-g");
   end Compiler;
end Hello_World;

Now press Ctrl+S to save the file.

Add hello world source code file

In the File Explorer title bar, select New File and name the file hello_world.adb.

Paste in the following source code:

with Ada.Text_IO;

procedure Hello_World is
begin
   Ada.Text_IO.Put_Line ("Hello Ada World!");
end Hello_World;

Now press Ctrl+S to save the file. Notice that your files are listed in the File Explorer view (Ctrl+Shift+E) in the side bar of VS Code:

File Explorer

You can also enable Auto Save to automatically save your file changes, by checking Auto Save in the main File menu.

The Activity Bar on the edge of Visual Studio Code lets you open different views such as Search, Source Control, and Run. You'll look at the Run view later in this tutorial. You can find out more about the other views in the VS Code User Interface documentation.

Currect project file configuration

It's important to configure the current project file setting. Open Settings View wiht menu File > Preferences > Settings (Ctrl+Comma), select Workspace tab, click Extensions/Ada and scroll to the Project File input field. Type hello_world.gpr value.

Ada Settings View

Explore IntelliSense

In the hello_world.adb file, hover over Put_Line to see subprogram information. After the begin keyword, start typing Ada.Text_IO. as you would when calling a package procedure. You should immediately see a completion list that shows all the subprograms in the package, and a window that shows the entity information:

Tooltip window

You can press the Tab key to insert the selected name. Then, when you add the opening parenthesis, you'll see information about arguments that the subprogram requires.

Build hello_world

To build a simple project, you can use the ada: Build current project predefined task. Predefined tasks are VS Code tasks that are created by the extension itself.

To do that, just invoke the VS Code Command Palette via the 'Ctrl+Shift+B' shortcut (or Cmd+Shift+B on Mac OS): then search for the Run Task command and type gprbuild. Clicking on the gprbuild entry will show you all the gprbuild related tasks, in particular the ada: Build current project one. Select it and press ENTER (or click on it) to actually build your project.

If your are dealing with a complex project, that requires different build steps or more advanved options, you can create a custom tasks.json file to tell VS Code how to build (compile) the program. This task will invoke the gprbuild tool to create an executable file from the source code.

It's important to have hello_world.adb open in the editor because the next step uses the active file in the editor for context to create the build task in the next step.

From the main menu, choose Terminal > Configure Default Build Task. A dropdown appears showing various predefined build tasks for Ada compilers. Choose ada: Build current project.

This will create a tasks.json file in a .vscode folder and open it in the editor.

Your new tasks.json file should look similar to the JSON below:

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "gprbuild",
			"projectFile": "${config:ada.projectFile}",
			"problemMatcher": [
				"$ada"
			],
			"label": "ada: Build current project",
			"group": {
				"kind": "build",
				"isDefault": true
			}
		}
	]
}

Note: You can learn more about tasks.json variables in the variables reference.

The command setting specifies the program to run; in this case that is gprbuild. The args array specifies the command-line arguments that will be passed to gprbuild. These arguments must be specified in the order expected by the tool.

This task tells gprbuild to take the project file name from settings (${config:ada.projectFile}), compile it, and create an executable file according to project file rules, resulting in hello_world for our example.

The label value is what you will see in the tasks list; you can name this whatever you like.

The "isDefault": true value in the group object specifies that this task will be run when you press Ctrl+Shift+B. This property is for convenience only; if you set it to false, you can still run it from the Terminal menu with Tasks: Run Build Task.

Running the build

  1. To run the build task defined in tasks.json, press Ctrl+Shift+B or from the Terminal main menu choose Run Build Task.

  2. When the task starts, you should see the Integrated Terminal panel appear below the source code editor. After the task completes, the terminal shows output from the compiler that indicates whether the build succeeded or failed. For a successful g++ build, the output looks something like this:

Build Task Terminal

  1. Create a new terminal using the + button and you'll have a terminal running your default shell with the helloworld folder as the working directory. Run ls .objs and you should now see the executable hello_world (no file extension).

Bash terminal

  1. You can run helloworld in the terminal by typing .objs/helloworld.

Check current file

Another task (ada: Check current file) could be used to quickly check syntax and semantic of the current file in the editor. If the compiler finds some errors VS Code will populate Problems view and highlight corresponding lines in the editor. It's handy to have a keyboard shortcut for this task. To create one:

  • Click View > Command Palette... (Ctrl+Shift+P) and type Preferences: Open Keyboard Shortcuts (JSON)

  • Append this to the shortcut list:

      {
          "key": "alt+v",
          "command": "workbench.action.tasks.runTask",
          "args": "ada: Check current file",
          "when": "editorLangId == ada"
      },

Debug hello_world.adb

Next, you'll create a launch.json file to configure VS Code to launch the GDB debugger when you press F5 to debug the program.

Our extension already provides the Native Debug to debug Ada code: this section will use it to demonstrate how Ada debugging works in VS Code.

From the main menu, choose Run > Add Configuration.... You'll then see a dropdown for various predefined debugging configurations. Choose GDB (LLDB could also work).

VS Code creates a launch.json file, opens it in the editor:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "gdb",
            "request": "launch",
            "target": "./bin/executable",
            "cwd": "${workspaceRoot}",
            "valuesFormatting": "parseText"
        }
    ]
}

In the JSON above, target specifies the program you want to debug. Replace its value with the executable file name (".objs/hello_world" in our case). To make sure that target binary is up to date, add preLaunchTask into the configuration:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "gdb",
            "request": "launch",
            "target": "./bin/executable",
            "cwd": "${workspaceRoot}",
            "valuesFormatting": "parseText",
            "preLaunchTask": "ada: Build current project",
        }
    ]
}

Let's replace hello_world.adb with something more complex:

with Ada.Text_IO;

procedure Hello_World is
   procedure Print (Text : String) is
   begin
      Ada.Text_IO.Put_Line (Text);
   end Print;
   
   Text : String := "Hello Ada World!";
begin
   Print (Text);
   Text := "xxxxx xxx xxxxx.";
   Print (Text);
end Hello_World;

By default, the Native Debug extension won't add any breakpoints to your source code. Let's put a breakpoint to the line with Print call. To do this switch to the hello_world.adb tab in the code editor, putting the insertion point somewhere on the Print statement, and pressing F9. A red dot appears in the gutter on the left to indicate that a breakpoint has been set on this line.

Breakpoint in Main

Start a debugging session

  1. Go back to hello_world.adb so that it is the active file.

  2. Press F5 or from the main menu choose Run > Start Debugging. Before you start stepping through the code, let's take a moment to notice several changes in the user interface:

    • The Integrated Terminal appears at the bottom of the source code editor. In the Debug Output tab, you see output that indicates the debugger is up and running.

    • The editor highlights the statement where debugger stops on the breakpoint:

      Breakpoint highlighted

    • The Run view on the left shows debugging information. You'll see an example later in the tutorial.

    • At the top of the code editor, a debugging control panel appears. You can move this around the screen by grabbing the dots on the left side

      Debugging controls

Step through the code

Now you're ready to start stepping through the code.

  1. Click F10 or press the Step over icon in the debugging control panel.

    Step over button

    This will advance program execution to the assignment statement, and skip over the Print procedure call. See value of the Text variable on the left panel. Also take a look at Debug Console to see the Put_Line output.

  2. Press Step over again to advance to the next statement in this program (skipping over assignment statement execution). Notice the change in the Variables window on the side.

    Variables view

  3. To quickly view the value of any variable while execution is paused on a breakpoint, you can hover over it with the mouse pointer.

  4. Try Step Into button to step in the Print procedure.

Reusing your Ada configuration

VS Code is now configured to use Ada. The configuration applies to the current workspace. To reuse the configuration, just copy the JSON files to a .vscode folder in a new project folder (workspace) and change the names of the project file and executables as needed.

Troubleshooting

TBD

Next steps

  • Explore the VS Code User Guide.
  • Create a new workspace, copy your .json files to it, adjust the necessary settings for the new workspace path, program name, and so on, and start coding!
Clone this wiki locally