Search code examples
cvisual-studio-codeconfigurationheader-files

How to configure so that you don't have to type the entire path to headers in c in vscode


I'm testing using vscode to see its ability to edit code in c. I encountered a problem when configuring the headers path, to facilitate header imports, since I place them in separate folders for organization, I configured the Microsoft C/C++ extension to add the include folder as the path to the headers, however doesn't seem to work

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/include"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c23",
            "cppStandard": "c++17",
            "intelliSenseMode": "linux-gcc-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}/include",
                    "${workspaceFolder}/src"
                ],
                "limitSymbolsToIncludedHeaders": false,
                "databaseFilename": ""
            }
        }
    ],
    "version": 4
}

this is the c_cpp_properties file that was created, but it doesn't seem to do anything.

i'm still receving this error:

Iniciando o build...
/usr/bin/gcc -fdiagnostics-color=always -g /home/user/Codes/C/TestProject/src/*.c -o /home/user/Codes/C/TestProject/src/../output/Main
/home/user/Codes/C/TestProject/src/Main.c:2:10: fatal error: List.h: No such file or directory
    2 | #include "List.h"
      |          ^~~~~~~~
compilation terminated.

Build concluída com erro(s).

Solution

  • Note

    This answer is mostly copied from my own answer to another question Error in VSCode while compiling for the first time in C

    c_cpp_properties.json

    c_cpp_properties.json is used by VSCode to give Intellisense the information it needs to do stuff like view documentation, find compilation errors and autocomplete. It has no effect on the actual compilation.

    Compiling with GCC

    If you have just one main.c, then you can just pass it straight to GCC and it will compile no questions asked.

    gcc ./main.c -o program.exe
    

    If you want to debug it then also tell GCC to add a debug symbols using -g or -g3 and if you want to set the optimization level then pass one of these -O0, -O1, or -O3.

    If you have a additional files in a folder, with the following structure:

    project
     |
     |- library_1
     |   |
     |   |- library_1.h
     |   |- library_1.c
     |
     |- main.c
    

    you can pass something like this to GCC.

    gcc main.c -I ./my_header library_1/library_1.c -o program.exe
    

    And it would compile. But as the number of files and increases, this command will become insanely large and it'd be impractical to type it on the terminal every time.

    Using CMake

    If you have lots of files than you can use CMake to manage the builds and pass on stuff to GCC automatically. A simple CMakeLists.txt would be something like this.

    # Tell CMake about your project name and version etc
    cmake_minimum_required(VERSION 3.19)
    set(PROJECT_NAME "your_project")
    project(${PROJECT_NAME} VERSION 0.1 LANGUAGES C CXX)
    
    # Add your executable and attach it to main.c
    add_executable(${PROJECT_NAME} main.c)
    
    # Add your library folders
    add_subdirectory(library_1)
    add_subdirectory(library_2)
    add_subdirectory(library_3)
    add_subdirectory(library_4)
    

    But keep in mind that each library folder would also have a CMakeLists.txt. Personally I like to make a folder with the library name, make a .c and .h file with the same name. Like this.

    library_1
      |- library_1.h
      |- library_1.c
      |- CMakeLists.txt
    

    And then put this in the library_1 cmake.

    get_filename_component(CURRENT_DIR_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
    target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${CURRENT_DIR_NAME}.c)
    target_include_directories(${PROJECT_NAME} PRIVATE .)
    

    It automatically picks up the library name and the .c and .h file names, so you can just copy paste this in all your libraries.

    And then you can build like this

    cmake -G Ninja -B build
    ninja -C build
    

    It'll put the executable in the build folder.

    VSCode Extension

    I am working on a VSCode extension that does all of these steps for you, and creates a pre-configured CMake project. It also provides buttons for cleaning, building, running, debugging and testing those projects so you don't have to deal with the terminal again and again. And it also checks for missing build tools so the user doesn't have to deal with installations and configurations.

    I'm calling it C Toolkit.

    So as the name suggests it only creates pre-configured projects in C, not C++. But you can create projects and rename the files and it would probably work I think. Lemme know if you decide to use it and if it solves your problem.