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.

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:
- Inside the project root folder create a new folder named .vscode
- 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.

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:

One way to run tasks is from the Terminal Menu:

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

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"]
}
}

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
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 1
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 2
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 3
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 4
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 5
- Visual Studio Code for C/C++ with ARM Cortex-M: Part 6
- Visual Studio Code website: https://code.visualstudio.com/
- Visual Studio Code: Tasks Documentation
- Template and example files on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/VisualStudioCode
- Visual Studio Code Shortcuts: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf
There are several task related entries in the Terminal menu, I think they are easier to use than via the Command Palette.
LikeLiked 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.
LikeLike
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.
LikeLiked 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.
LikeLike
> 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. 😉
LikeLiked 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 🙂
LikeLike
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.
LikeLiked by 1 person
To my knowledge, this is not possible, or at least I did not see how.
LikeLike
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.
LikeLike
Yes, I do use the ProblemMatcher, that was the logical choice for me.
LikeLike
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).
LikeLiked by 1 person
Hi Martin, did you manage to configure the ms-vscode.cmake-tools extension to use two separate Debug/Release build configurations?
LikeLiked by 1 person
Yes that’s possible. see https://gist.github.com/bearsh/75251a7cb2926ea5f58f6fad5073b3a2 especially cmake-variants.yaml and settings.json
LikeLiked 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.
LikeLiked 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?
LikeLike
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.
LikeLike
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.
LikeLike
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…
LikeLiked 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 🙂
LikeLike
> 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.
LikeLiked 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.
LikeLike
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.
LikeLiked by 1 person
Hi Martin,
thanks for that tip with adding CMAKE_TOOLCHAIN_FILE. I tried that but it did not work because I had it *after* project(…) (ahhhrtg!). That’s why I had to use it on the commandline as argument. Now if I have it before ‘project’ I can simplify the command line (updated the post already) which is great. So this is a big help, but unfortunately it is still not recognized as a kit, and all the cmake commands don’t work 😦
LikeLike
ok, I just checked with my configuration. You also need to place an additional config file in your .vscode folder: https://gist.github.com/bearsh/75251a7cb2926ea5f58f6fad5073b3a2#file-vscode_cmake-kits-json (as .vscode/cmake-kits.json)
LikeLiked by 1 person
Martin,
indeed, that makes it work! Thank you so much! Now I only need to write another article just about this 🙂
LikeLike
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.
LikeLiked 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 🙂
LikeLike
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 4 | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 2 | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 1 | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 5 | MCU on Eclipse
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.
LikeLiked 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!
LikeLike
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 6 | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 7 – FreeRTOS | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 8 – xPack C/C++ Managed Build Tools | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 9 – RTT | MCU on Eclipse
Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 10 – Assembly Stepping | MCU on Eclipse