12

As the title said, can I populate automatically c_cpp_properties.json from an existing Makefile?

Edit:

For others trying to import makefiles, I have found a set of scripts that perform exactly what I wanted to achieve, the management of STM32 embedded projects through VS Code. If you dig into the scripts folder you can find the make parser and the VSCode project files populator.

Here the repo, enjoy!

Andrea Nisticò
  • 466
  • 2
  • 4
  • 11
  • You can search the VS Code Marketplace, but this seems unlikely to exist. Which properties do you expect to import from your makefile(s)? – Reinier Torenbeek Dec 07 '18 at 22:35
  • searched through it but no luck. The problem is that I have an embedded project that is autogenerated by a software (cubemx fot stm32). The project has a makefile and I would like to open it through VS Code and have the suggestions, linking to files when I ctrl click ecc. When I open it as a folder VS Code complains about variables not defined because it does not have the info. I think for the linter to work it needs include files and, source files maybe? – Andrea Nisticò Dec 08 '18 at 17:16
  • Thanks for elaborating. Although there is no satisfying answer to your question, I responded with some hints that may help you. Good luck! – Reinier Torenbeek Dec 08 '18 at 22:13

4 Answers4

18

This answer may not entirely give you what you want, but hopefully it helps you setting up your VS Code environment.

In your question title, you mention "Makefile projects", which is an indication that you have the wrong impression that (GNU) Makefiles capture project settings in a way similar to Visual Studio project files do. Makefiles do not work like that and the short answer to your question is No, there does not seem to be a way to "import" Makefiles into VS Code and have it automatically set values in your c_cpp_properties.json file.

Having said that, there are some other mechanisms that may help you getting started with VS Code in your situation, depending on the other elements you have in your toolchain.

VS Code works with the premise that it opens one or more directories in your file system. When you do so, it will automatically scan all its subdirectories, display the tree and do linting (if enabled) to detect problems. Indeed, include directories need to be added manually to your c_cpp_properties.json file but to add all your subdirectories recursively to the list of include directories, you can use the expression

"${workspaceRoot}/**"

as one of the elements in your includePath setting. See the blog post Visual Studio Code C/C++ extension May 2018 Update – IntelliSense configuration just got so much easier! for more details. That often resolves a lot of the missing symbols. If you are using external or 3rd party libraries as well, then you have to add those to your includePath setting manually, there is no way around that.

Additionally, you can create VS Code Tasks to execute your make command to your liking. This is explained here: Integrate with External Tools via Tasks. The Microsoft C/C++ Extension comes with a set of so-called problemMatchers that parse the output of your command and can interpret that for certain known compilers. You will see hyperlinks for errors and warning to navigate directly to the associated location in your code.

An example of such a Task may look like this:

    {
        "label": "Build All Debug",
        "type": "shell",
        "command": "make -f path/to/Makefile DEBUG=1",
        "group": {
            "kind": "build",
            "isDefault": true
        },
        "presentation": {
            "reveal": "always",
            "panel": "new"
        },
        "problemMatcher": [
            "$gcc"
        ]
    }
Reinier Torenbeek
  • 16,669
  • 7
  • 46
  • 69
  • Thanks, great answer. Digging into this issue I found a makefile parser here: https://github.com/platformio/builder-framework-libopencm3/blob/de7fa9adef178a8b10dbaddfb6a1073f6f1bef01/libopencm3.py and some useful resources. I discovered that I had a define missing in my c_cpp_properties file, now the linter is working as expected. I will automate the process in the future, thanks again – Andrea Nisticò Dec 10 '18 at 10:58
  • 1
    Glad it helped @AndreaNisticò . Ah, I forgot about the #defines, those are important too indeed. I will add that remark to my answer later, when I have some more time. The makefile parser looks interesting too, will check that out as well. – Reinier Torenbeek Dec 10 '18 at 15:35
  • My idea for the future is to create a Makefile template for this kind of embedded projects and populate it with a python script. I may even translate it to CMake since I am quite a fan of it, but I need to understand better Makefiles. – Andrea Nisticò Dec 11 '18 at 10:52
10

Visual Studio Code's Intellisense extension for C/C++ supports a compile_commands.json database. Some makefile utilities can generate these databases by themselves, but I don't have any experience using them to do so. With GNU make, you'll need some kind of helper script or tool. I used the python package compiledb:

sudo pip install compiledb
cd projectfolder
make clean
compiledb make

After running that, you should end up with a compile_commands.json file. Then, in VS Code, you need to edit c_cpp_properties.json for the workspace in question. One way to open it is by clicking the configuration name in the lower right corner of the status bar then clicking "Edit Configurations (json)". Or, you can open the command palatte (CTRL + SHIFT + P on my system), and entering C/C++: Edit configurations (JSON)

Then, in configuration you are using, add the property "compileCommands": "${workspaceFolder}/compile_commands.json"

Full example:

{
    "configurations": [
        {
            "name": "geany",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "gcc-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}/**"
                ],
                "limitSymbolsToIncludedHeaders": true
            },
            "compileCommands": "${workspaceFolder}/compile_commands.json"
        }
    ],
    "version": 4
}

Now, Visual Studio code's Intellisense analysis should be using the exactly correct include directories, define directives, and other command line compiler flags unique to each individual source file.

dutchkin
  • 121
  • 1
  • 3
  • 1
    `sudo pip install` can corrupt packages installed by the Linux distro. `pip install --user` won't. – nyanpasu64 Sep 12 '20 at 10:32
  • The `bear` utility seems to do a fine job generating `compile_commands.json` from makefiles. (on Ubuntu, you can install the package with `apt install bear`) – undercat Jan 13 '21 at 11:22
2

For others trying to import makefiles, I have found a set of scripts that perform exactly what I wanted to achieve, the management of STM32 embedded projects through VS Code. If you dig into the scripts folder you can find the make parser and the VSCode project files populator.

Here the repo, enjoy!

Andrea Nisticò
  • 466
  • 2
  • 4
  • 11
  • 1
    From the README you linked to : this project has been replaced with https://marketplace.visualstudio.com/items?itemName=ms-vscode.makefile-tools – Eric Duminil Feb 18 '23 at 20:11
1

GNU Make is commonly used to compile C projects, but it can produce any sort of output files you want.

You can create a script for this purpose, or you can do it from another makefile, eg: VSCode.mk that you include in your top level Makefile.

This solution is using One Shell but if that is not viable a separate script would look nicer.

The @ makes your output nicer.

Most likely you can't safely copy paste this code because Make uses literal tabs, not whitespace.

.ONESHELL:
SOURCE_DIRECTORY := src
DEFINED_VALUE := 1

# Recipe:
.vscode/c_cpp_properties.json:
    @
    cat << EOF > "$@"
    {
    "configurations": [
        {
        "name": "Linux",
            "includePath": [
                "\$${workspaceFolder}/$(SOURCE_DIRECTORY)*"
            ],
            "defines": [
                "DEFINED_VALUE=$(DEFINED_VALUE)"
            ],
            "compilerPath": "$(CC)",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64",
            "browse" : {
                "limitSymbolsToIncludedHeaders" : true
            }
        }
    ],
        "version": 4
    }
    EOF
szmoore
  • 924
  • 10
  • 18