Gunter
Gunter

Reputation: 382

How to switch between build targets in Visual Studio Code?

We are trying to move from Code::Blocks to Visual Studio Code for C/C++ development. The main reason is the way better code completion provided through IntelliSense. But the comparison of the two shall not be the topic here.

In order to get our old projects compiling, we set up a makefile and tasks in Visual Studio Code. This works fine so far.

Where things became complicated are different build targets. Let's say we have an example project, in which we need to compile two versions of our program, which are about 95% the same. So in Code::Blocks-times, we decided to keep everything in one project, but distinguish the different source code bits via defines and ifdef. So you select the proper build target, which appends the defines to the gcc call and the correct version of the two is built. To make things a little more complicated each version has also a debug and release target. So it is four build targets in total:

So, our makefile, which we use in VS Code is setup that we can also select the build target and the proper versions are built. So far so good.

Now the C/C++-Extension and IntelliSense come into play. They use clang to "compile" the code on the fly for auto completion and highlighting code sections, which are actually used. Because our #defines (VERSION1 or VERSION2) for the different versions are only provided to the gcc compiler in the makefile, clang does not know about them. Without knowing them, the code sections are grayed out (which is not that much of a deal), but also auto completion does not work for variables, which happen to be declared in such a section.

Of course we can specify the defines in the c_cpp_properties.jsonand also make different build targets there. But this would mean, that we need to switch between build targets twice: first for the C/C++ extension and second for the makefile. I am pretty sure that people will forget one or the other and get frustrated.

So long story short: Is there a way to switch build targets in Visual Studio Code, which affect both IntelliSense and the actual build?

Upvotes: 5

Views: 11617

Answers (1)

Gunter
Gunter

Reputation: 382

Finally we found a solution. Actually, a colleague of mine did find it.

We need to adapt three files to get this working.

c_cpp_properties.json needs the definitions for the different build targets - called "configurations" in this file. This allows you to select the different configurations in the bottom right of VS Code once you are in a c-file.

{
    "configurations": [
        {
            "name": "DEBUG",
            "includePath": [
                 //...
            ],
            "defines": [
                 //...
            ],
            "compilerPath": "path/to/compiler",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        },
        {
            "name": "RELEASE",
            "includePath": [
                 //...
            ],
            "defines": [
                 //...
            ],
            "compilerPath": "path/to/compiler",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ]
}

tasks.json needs a task, which read the currently used c_cpp-configuration and pass this as argument to the make file.

{
    //...
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "make
            "args": [
                "CONFIG_NAME=${command:cpptools.activeConfigName}"
            ]
        }
    ]
}

Finally, in your makefile you can check CONFIG_NAME and make your final adjustments. Below is just one example, which is not complete (deducting from not finding "DEBUG" that we want to build "RELEASE" might be a little daring, but you get the point). Of course you can check also other things or you can match the full configuration name. We have quite a bunch of c_cpp-configurations, which follow a certain internal naming scheme. The concept in the makefile shown below enables us to check for different parts of the config name and build the corresponding flags in the makefile.

# ...
ifneq (,$(findstring DEBUG,$(CONFIG_NAME)))
    CFLAGS += -DDEBUG
else
    CFLAGS += -DRELEASE
endif
# ...

Again, I need to acknowledge that this solution was actually found by my colleague.

Upvotes: 7

Related Questions