23
votes

Note that I'm using VS Code on Ubuntu 17.10 and using the GCC Compiler.

I'm having trouble building a simple program which makes use of additional .ccp files. I'm probably missing something obvious here as I'm fairly new to programming but I'll explain what I've done so far. This is something that is stopping me from continuing with a tutorial I'm doing.

I have written a very simple program to demonstrate my point as follows.

main.ccp


#include <iostream>
#include "Cat.h"

using namespace std;

int main ()
{

speak();

return 0;
}

Cat.h


#pragma once



void speak();

Cat.ccp


#include <iostream>
#include "Cat.h"

using namespace std;

void speak()
{
std::cout << "Meow!!" << std::endl;

}

This simple program builds in both Codeblocks and Visual Studio Community 2017 no problem and I can't figure out what I need to do to make it run. This error at the bottom indicates that the Cat.ccp file is not being picked up at all. If I was to drop the definition from this Cat.ccp into the header file the program compiles and runs fine but I need to make use of that .ccp file as I understand this is the accepted way of separating code. I'll note that all the files are in the same folder too.

I understand that I may need to tell VS Code where to look for the Cat.ccp file but it's strange to me that it finds the header in the same location. Nevertheless, after looking online I've been reading that I may need to place a directory into the c_cpp_intellisense_properties.json. Here's what mine looks like.

{
"configurations": [
    {
        "name": "Mac",
        "includePath": [
            "/usr/include",
            "/usr/local/include",
            "${workspaceRoot}"
        ],
        "defines": [],
        "intelliSenseMode": "clang-x64",
        "browse": {
            "path": [
                "/usr/include",
                "/usr/local/include",
                "${workspaceRoot}"
            ],
            "limitSymbolsToIncludedHeaders": true,
            "databaseFilename": ""
        },
        "macFrameworkPath": [
            "/System/Library/Frameworks",
            "/Library/Frameworks"
        ]
    },
    {
        "name": "Linux",
        "includePath": [
            "/usr/include/c++/7",
            "/usr/include/x86_64-linux-gnu/c++/7",
            "/usr/include/c++/7/backward",
            "/usr/lib/gcc/x86_64-linux-gnu/7/include",
            "/usr/local/include",
            "/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed",
            "/usr/include/x86_64-linux-gnu",
            "/usr/include",
            "/home/danny/Documents/C++_Projects/24_-_Classes/Cat.cpp",
            "${workspaceRoot}",
            "/home/danny/Documents/C++_Projects/24_-_Classes/",
            "/home/danny/Documents/C++_Projects/24_-_Classes/.vscode",
            "/home/danny/Documents/C++_Projects/24_-_Classes/.vscode/Cat.cpp"
        ],
        "defines": [],
        "intelliSenseMode": "clang-x64",
        "browse": {
            "path": [
                "/usr/include/c++/7",
                "/usr/include/x86_64-linux-gnu/c++/7",
                "/usr/include/c++/7/backward",
                "/usr/lib/gcc/x86_64-linux-gnu/7/include",
                "/usr/local/include",
                "/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed",
                "/usr/include/x86_64-linux-gnu",
                "/usr/include",
                "${workspaceRoot}",
                "/home/danny/Documents/C++_Projects/24_-_Classes/",
                "/home/danny/Documents/C++_Projects/24_-_Classes/.vscode/Cat.cpp"
            ],
            "limitSymbolsToIncludedHeaders": true,
            "databaseFilename": ""
        }
    },
    {
        "name": "Win32",
        "includePath": [
            "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
            "${workspaceRoot}"
        ],
        "defines": [
            "_DEBUG",
            "UNICODE"
        ],
        "intelliSenseMode": "msvc-x64",
        "browse": {
            "path": [
                "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
                "${workspaceRoot}"
            ],
            "limitSymbolsToIncludedHeaders": true,
            "databaseFilename": ""
        }
    }
],
"version": 3
}

At one point I wondered if I need to add a double command in there to tell the compiler to build both .ccp files in the tasks.json but I haven't managed to figure out how to do that, or even if that's the right approach.

tasks.json


{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
    {
        "label": "Build",
        "type": "shell",
        "command": "g++ -g /home/danny/Documents/C++_Projects/24_-_Classes/main.cpp -o Classes",
        "group": {
            "kind": "build",
            "isDefault": true
        },
        "problemMatcher":"$gcc"
    }
]
}

Appreciate any help. And just in case you're wondering, the reason I don't just finish the tutorial in Codeblocks or VS Community is that I like to know what's going on under the hood in most things. Plus I'd like to get VS Code working for me as it's been great so far.

12
I dont know anything about VS Code, but you definitely need to tell it to compile and link both CPP files into the executable. The header file is found because you reference it in main.cpp. - Cris Luengo

12 Answers

7
votes

If you have multiple files and one depends on a cpp file for another, you need to tell g++ to compile it as well, so the linker can find it. The simplest way would be:

$ g++ Cat.cpp main.cpp -o Classes

As a side note, you should probably compile with warnings, minimally -Wall, likely -Wextra, and possibly -Wpedantic, so you know if something you're doing is problematic.

37
votes

in tasks.json:

        "label": "g++.exe build active file",
        "args": [
            "-g",
            "${fileDirname}\\**.cpp",
            //"${fileDirname}\\**.h",
            "-o",
            "${fileDirname}\\${fileBasenameNoExtension}.exe",
        ],

in launch.json:

"preLaunchTask": "g++.exe build active file"

it will work if your sources are in separated folder

11
votes

feeling lazy,

This is tasks.json of vscode for linux distros, to compile multiple cpp files.

{
"version": "2.0.0",
"tasks": [
    {
        "type": "shell",
        "label": "C/C++: g++ build active file",
        "command": "/usr/bin/g++",
        "args": [
            "-g",
            "${fileDirname}/*.cpp",
            "-o",
            "${fileDirname}/${fileBasenameNoExtension}"
        ],
        "options": {
            "cwd": "/usr/bin"
        },
        "problemMatcher": [
            "$gcc"
        ],
        "group": {
            "kind": "build",
            "isDefault": true
        }
    }
]

}

8
votes

This is a windows answer for the same problem:

I was struggling with this as well until I found the following answer at https://code.visualstudio.com/docs/cpp/config-mingw :

You can modify your tasks.json to build multiple C++ files by using an argument like "${workspaceFolder}\\*.cpp" instead of ${file}. This will build all .cpp files in >your current folder. You can also modify the output filename by replacing "${fileDirname}\\${fileBasenameNoExtension}.exe" with a hard-coded filename (for >example "${workspaceFolder}\\myProgram.exe").

Note that the F in workspaceFolder is capitalized.

As an example, in my tasks.json file in my project, the text in between the brackets under "args" originally appeared as follows:

"-g",
  "${file}",
  "-o",
  "${fileDirname}\\${fileBasenameNoExtension}.exe"

This gave me reference errors because it was only compiling one and not both of my files.

However, I was able to get the program to work after changing that text to the following:

"-g",
"${workspaceFolder}\\*.cpp",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
3
votes
"tasks": [
    {
        "label": "echo",
        "type": "shell",
        "command": "g++",
        "args":[
            "-g","main.cpp","cat.cpp"
        ],
        "group": {
            "kind": "build",
            "isDefault": true
        }
    }

Just add cat.cpp in args and then try to run. It should run without error on VS code

1
votes

On the terminal tab of your VS Code program write the following:

$ g++ nameOne.cpp nameTwo.cpp -o a.out  
$ ./a.out
0
votes

For Mac you can use

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "shell: g++ build active file",
            "command": "/usr/bin/g++",
            "args": [
                "-g",
                "-Wall",
                "-Wextra",
                "-Wpedantic",
                "${workspaceFolder}/*/*.cpp",
                "${fileDirname}/*.cpp",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

This will compile all the cpp file with all the directories which contain .cpp files.

0
votes

If you are using linux then know how to use make. If save a lot of time and effort. If you have even 10s or 100s of files and some dependencies are there then just make a Makefile once and every time you compile just use one command make and that will do all the work for you. Even you can make a keyboard shortcut for that command in VSCode.

Check out here to use make and here for using that in VSCode.

0
votes

credits: Anns98.

Remember below args are belongs to g++.10.2.0 C++17.

You should tweak your compiler implicitly/explicitly to achieve the consistency you desire.

CHECKOUT: winlibs (gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r5) looks promising.

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "cppbuild",
      "label": "retr0C++",
      "command": "C:\\mingw64\\bin\\g++",
      "args": [
        "-std=c++17",
        "-I",
        "${fileDirname}\\includes",
        "-o",
        "${fileDirname}\\${fileBasenameNoExtension}.exe",
        "-g",
        //"${file}",
        "${fileDirname}\\**.cpp"
      ],
      "options": {
        "cwd": "C:\\mingw64\\bin"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "compiler: C:\\mingw64\\bin\\g++"
    }
  ]
}

0
votes

On Windows the solution is

{
"version": "2.0.0",
"tasks": [
    {
        "type": "cppbuild",
        "label": "C/C++: cl.exe compila il file attivo",
        "command": "cl.exe",
        "args": [
            "/Zi",
            "/EHsc",
            "/nologo",
            "/Fe:",
            "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "*.c"
        ],
        "options": {
            "cwd": "${workspaceFolder}"
        },
        "problemMatcher": [
            "$msCompile"
        ],
        "group": {
            "kind": "build",
            "isDefault": true
        },
        "detail": "compilatore: cl.exe"
    }
]

}

0
votes

I had similar problem, and it was not easy to find answer which I fully understand. First thing you need to understand is that all .cpp files used in your project need to be compiled for the linker. for project with one .cpp file there is relatively no issue. you simply need to tell g++ which .cpp file need to be compiled by running the following command in the terminal from the root directory:

g++ -g main.cpp -o mainApp 

This tells g++ to compile main.cpp an create a consolApp (output file) named mainApp.

  1. In the case of a project with more than one .cpp file,

|--root

  • |--main.cpp}
  • |--include1
    • |-- foo1.h
    • |-- foo1.cpp
  • |-- include2
    • |-- foo2.h
    • |-- foo2.cpp
  • |-- foo3.cpp

To compile this project and build the output file we run this in the terminal:

g++ -g main.cpp include1/foo1.cpp include2/foo2.cpp foo3.cpp -o mainApp

Note that the order in which we pass the .cpp files to be compiled doesn't really matter.

  1. You can already understand that for a very large project writing that command will be very tedious. you can rewrite is as follow

    g++ -g ./*.cpp include1/*.cpp include2/*.cpp -o mainApp

This simply tells g++ to compile all .cpp file in the root, include1 and include2 folders.

  1. What if your project has a lot of folders, you can simply run it recursively

    g++ -g ./**/*.cpp -o mainApp

This is kind of telling g++ to go through root folder and through other folder and compile all .cpp files it will find.

  1. To do the same thing in vscode, go to the tasks.json file, and in 'args' add :

    "${workspaceFolder}/.cpp",
    "${workspaceFolder}/**/
    .cpp",

This is the equivalent of :

g++ -g ./**/*.cpp -o mainApp
0
votes

after finding a lot of solutions I find this only working, install the code runner extension. in settings, go to open settings in the right upper corner and simply paste this line in setting.json before the end of last closing bracket }

"code-runner.executorMap": {
    "cpp": "cd $dir && g++ *.cpp -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
},

[settings.json --> file looks like] : https://i.stack.imgur.com/pUBYU.png