Visual Studio Code for C/C++ with ARM Cortex-M: Part 3 – Build

This is the third part in a series to get up and running using the Microsoft Visual Studio Code for embedded development on ARM Cortex-M. So far we have installed the needed tools, created a project and are able to build it from the command line. Now it is about how execute directly scripts or the build from the IDE.

Building with a Visual Studio Code Task

Outline

In the previous tutorial I have used the command line to build the project. This is great and very flexible, but it would be better if I could launch the scripts or commands in an easy way from the IDE. The Visual Studio Code is primarily an editor, but it has a framework implemented to to execute scripts or launch programs without entering them on the command line.

The idea is that we can press <CTRL>+<SHIFT>+B to perform a build. You can find the keybindings in https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf or with the menu File > Preferences > Keyboard Shortcuts:

Tasks

There are different ways to create and configure Visual Studio Code Tasks, see Visual Studio Code: Tasks Documentation. An easy and simple way is to create a folder named .vscode and add a tasks.json file to it:

  1. Inside the project root folder create a new folder named .vscode
  2. Inside that folder create a new file named tasks.json and add the following content (available on GitHub):
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "Build Project",
            "command": "cmake --build .",
            "options": {
                "cwd": "${workspaceFolder}/build"
            },
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "base": "$gcc", 
                "fileLocation": ["relative", "${workspaceFolder}/build"]
            }
        }
    ]
}

This creates a ‘task’ to build the project with a “shell” (Console) command. the “cmake –build .” command we have seen in the previous tutorial.

For the current directory it uses the “${workspaceFolder}/build” because this shall be the current working directory for the cmake.

With the following group it is marked as the default build command which assigns it to the <CTRL>+<SHIFT>+<B> shortcut:

"group": {
   "kind": "build",
   "isDefault": true
},

The “problemMatcher” assigns that the matcher for gcc to scan the console output for messages from gcc, so I can see things in the ‘Problems’ view.

gcc problem matcher

This is just a minimal task, and by far not prefect, but it gets us running.

Build

Now I can just press <CTRL>+<SHIFT>+<B> to build the project, with the output in the Terminal on the bottom:

tasks.json

One way to run tasks is from the Terminal Menu:

Otherwise, the tasks can be run from the command palette (<CTRL>+<SHIFT>+<P>):

Command Palette

And then filter and select the task to run:

More Tasks

The same way other tasks can be added to the list and executed. Below a task added to do a ‘clean with a build’ cmake command: add the following to the tasks list (separated with comma):

{
            "type": "shell",
            "label": "clean & build",
            "command": "cmake --build . --clean-first",
            "options": {
                "cwd": "${workspaceFolder}/build"
            },
            "group": "build",
            "problemMatcher": {
                "base": "$gcc", 
                "fileLocation": ["relative", "${workspaceFolder}/build"]
            }
}
Second Task added to tasks.json (Note: use the source code posted in the article)

There can be only one ‘default build’ task, that’s why it is just added to the ‘build’ group.

Selecting Tasks to Run

Executing the default build task is easy with <CTRL>+<SHIFT>+<B>.

Executing arbitrary tasks I have defined took me a while to find out. The best way I have found is this one:

First, press <CTRL>+<P>. In the following dialog enter “task ” (note the space at the end):

This lists the tasks and I can select the one I would like to run.

Another way is again to use the Terminal menu:

If you know of a better way without the need to install extensions, I want to hear about it.

Summary

With this I have assigned a default build task and can use a shortcut to execute it. Additionally I can define custom tasks or integrate scripts into the IDE.

For a more advanced setup: have a look at extensions like the xPack C/C++ Manged Build Tools.

Next article will be about how to debug the executable on the board.

Happy Coding 🙂

Links

38 thoughts on “Visual Studio Code for C/C++ with ARM Cortex-M: Part 3 – Build

  1. There are several task related entries in the Terminal menu, I think they are easier to use than via the Command Palette.

    Liked by 1 person

    • Hi Liviu,
      thanks for that hint. I did follow the Microsoft documentation and missed the fact that I can run the Tasks from the ‘Terminal’ menu :-(. In my thinking I would look for them in the ‘Run’ menu or would expect a ‘Build’ menu. It makes sense to have them in the ‘Terminal’ menu (because it runs with a terminal session), still I would not have thought about looking it up there. I feel stupid now…
      Post is updated now.

      Like

      • You’re welcome!

        Yes, the VS Code natural way of performing build related actions is by defining ‘tasks’, and the first choice for managing tasks is via the Terminal menu.

        However please note that the xPack C/C++ extension automatically defines task for all relevant actions (prepare/build/clean/execute/etc) for each build configuration, so there is no need to manually contribute to the tasks.json file (actually to none of the .vscode files).

        Also please note that, in addition to the Terminal menu and the Command Palette, VS Code provides an even more convenient way of navigating through configurations and actions, by allowing extensions to devine custom explorers in the lower left part of the screen, which easily represent hierarchical items.

        This explorer can have Run icons associated to different actions, so triggering actions (like builds) is only one mouse click away, from any configuration, which is very convenient.

        A screenshot of such a dual configuration project, with buttons for actions can be seen at:

        https://xpack.github.io/vscode/quick-start/#perform-the-build

        As a conclusion, I somehow understand your desire to present a very basic configuration using only Microsoft extensions, but the result is far, far more complicated compared to a similar experience with Eclipse, you have to manually configure multiple files (see Martin’s collection of scripts) and you still do not get the same results.

        With the xPack Build extension you don’t have to do any of these, you don’t have to configure any specific .vscode files, you don’t have to configure paths to the build tools, you have strict control on which versions of the tools are used, you can run exactly the same actions from a terminal or from within VS Code, you can use the same workflow with CMake/meson/autotools/etc, and probably the list can go on.

        Liked by 1 person

        • Hi Liviu,
          thanks for all the details and very useful comments, multumesc! I understand as well the desire from many developers just first to go with a basic setup, to have a common ground first. If the xpack extension would be part of the MS standard installation and distribution (I wish it should be), or part of a standard package like CDT for Eclipse, that would be the way to go imho. Starting with simple things like be able to use a text editor and to compile a source file from the console is a first step every developer should do, and only then go up to things like using an IDE and going to more complex build actions. Because then they understand the basics and know how things work, and are not lost if something does not work as expected in the more complex environment. And I believe once developers have understood and mastered the ‘basics’ they even more appreciate the sophisticated extensions.
          Finally I hope (and I’m sure) Microsoft might watch this space and learn from it and making their tools better suited for embedded, if they want to be serious about it.

          Like

        • > If the xpack extension would be part of the MS standard installation and distribution (I wish it should be),

          The MS standard distribution of VS Code does not include the C/C++ or the CMake extensions either, users need to install them explicitly, as you already mentioned in the post; installing the xPack extension is just an extra item in that list.

          Actually it it even less work, since the xPack extension automatically brings the C/C++ and CMake extensions in, as dependencies, so if you have a plain VS Code and install only the xPack extension, you get everything you need. 😉

          Liked by 1 person

        • Yes, that will make perfect sense in one of the following articles. I did not limit the series, so there is plenty of room 🙂

          Like

        • With the xPack, is there a possibility to add a command (bind to key) to build current selected configuration? At the moment ctrl+cmd+b will only give possibility to compile with system compilers. It is somehow annoying to use the mouse to click the build action.

          Liked by 1 person

        • One more thing to ask, how can I get the errors/warnings from the compiling to be shown on “PROBLEMS”? Erich uses the action with ProblemMatcher. How can this be accomplished with the xPack? I guess this would also be answer to my first question.

          Like

  2. Why do you use tasks to trigger a build instead of the cmake extension? using the extension you can configure/build/clean your project by just calling the appropriate command or using the shortcut (F7 for build).

    Liked by 1 person

    • Hi Martin, did you manage to configure the ms-vscode.cmake-tools extension to use two separate Debug/Release build configurations?

      Liked by 1 person

        • Yeah, thank you for the link, but, without a proper documentation, I’m afraid I’m not smart enough to use that recipe to configure my multi-platform, multi-architecture, multi-toolchain, multi-tests, projects. 😦

          CMake in general, and the CMake integration into VS Code seem to require a PhD to do any useful things…

          BTW, try to configure a project that will run on 5 different platforms, with 4 different architectures, with tests which must run with different versions of the same toolchain, and you’ll see what I mean.

          Liked by 1 person

        • Hi Martin, I took a second look at your configuration, and I noticed that although you have two separate debug/release build folders, you placed the compile_commands.json file in the workspace folder, so you practically cannot simply switch between configurations, you have to do a full rebuild for the indexer to be updated. Is this intentional?

          Like

        • yes at least kind of. if I remember correctly, I could not find a way to configure multiple compile_commands.json in the c/c++ extension. but it is possible to copy the compile_commands.json after cmake creates it in the build folder.

          Like

        • Ok, it’s your choice, but, for those coming from Eclipse, the expected behaviour is to have both build configurations available in parallel, and, when switching between them, the indexer to automatically update the way the source code is displayed, by greying the dead code corresponding to the selected configuration.

          This behaviour is fully implemented by the VS Code xPack C/C++ Build extension, and everything is automated, actually the user has no .vscode specific files to tweak; none at all, like in Eclipse.

          Like

        • Liviu, I see your point.

          I just want to clarify:

          > … when switching between them, the indexer to automatically update the way the source code is displayed, by greying the dead code corresponding to the selected configuration

          with my configuration vscode just does this. If I switch the build configuration (cmake: Select Variant) the indexer gets updated and e.g. grays out dead code…

          Liked by 1 person

    • Because the CMake extension is looking up for a ‘kit’ and it would find a ‘kit’ for Cortex A which is for a Raspberry, so code would be messed up. I did not tap into the whole ‘kit’ thing. But in essence the Cmake extension did not work the way I would expect it. Maye it is only me, but this area looks like a big obscure thing inside VSC. Probably it is me to blame about it (did not fully check your templates), but what always has working safe and according to what I wrote in the settings are the tasks. That’s why I have using them here: they are simple, easy to understand and they actually work 🙂

      Like

      • > in essence the Cmake extension did not work the way I would expect it. Maye it is only me, but this area looks like a big obscure thing inside VSC. Probably it is me to blame about it (

        It’s not only you, we’re at least two. 😦

        The CMake documentation in general is obscure, and there are a lot of weird use cases around.

        My needs (probably influenced by the Eclipse CDT supporting by default multiple build configurations), are definitely multi-platforms/architecture/toolchain, and the CMake plug-ins in Eclipse/extensions in VS Code, do not support this, everything happens in a single build folder, which, for me, is not enough.

        Liked by 1 person

        • >The CMake documentation in general is obscure, and there are a lot of weird use cases around.
          The documentation is pretty good on CMake in general, and StackOverflow is a great resource. I have used make for years and only CMake occasionally. Microsoft does support their own MSBuild, but I rather want to stick with CMake in combination with Ninja if possible.

          Like

      • Ah I see. I suppose setting the toolchain file in your main CMakeLists.txt should fix this.
        put `set(CMAKE_TOOLCHAIN_FILE “PATH_TO_YOUR_TOOLCHAIN_FILE”)` to the very top of your CMakeLists.txt (it has to be before project(…)). Now VSCode should recognize your ‘kit’ and you can use CTRL-SHIFT-P ‘cmake …’ to configure/build/clean/target selection/etc.

        Liked by 1 person

  3. Did you check if IntelliSense is accurate for your project, since I did not see you doing anything special for this.

    When using CMake, you should enable the generation of compile_commands.json, and inform the C/C++ extension about this.

    Also, and sorry for insisting on this, I still think that it would have been useful to show how to configure the two Debug/Release build configurations, and how to switch between them.

    Liked by 1 person

    • I did not talk about IntelliSense configuration yet because this is saved for later. For that small project in the current state it is not necessary so can be added later. But yes: Intellisense is a must for a larger or growing project.
      Same thing about multiple configurations like ‘Release’ or ‘Build’: they are not needed nor required in this stage. And again I agree that this is something for later. Keeping things simple for now and not boiling the ocean and trying to address all and everything. Plus that there can be room for follow-up parts of the series 🙂

      Like

  4. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 4 | MCU on Eclipse

  5. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 2 | MCU on Eclipse

  6. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 1 | MCU on Eclipse

  7. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 5 | MCU on Eclipse

  8. Firstly thank you for the blog.

    I have one suggestion for the problemMatcher in tasks.json file.

    “problemMatcher”: {“base”: “$gcc”, “fileLocation”: [“relative”, “${workspaceRoot}/build”]

    So you can click on the problem in the problems list and it showed it correctly in the editor.
    Without it was not possible at my configuration.

    Liked by 1 person

    • Hi Alexander,
      thanks, I finally managed to verify this. Indeed, without this the messages show up twice and half of them are not using the correct path. Your proposal fixed it :-). I have updated the article and my project(s) and now it works perfectly, thank you again!

      Like

  9. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 6 | MCU on Eclipse

  10. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 7 – FreeRTOS | MCU on Eclipse

  11. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 8 – xPack C/C++ Managed Build Tools | MCU on Eclipse

  12. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 9 – RTT | MCU on Eclipse

  13. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 10 – Assembly Stepping | MCU on Eclipse

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.