Search code examples
c++visual-studio-codeg++vscode-tasks

'Undefined reference' error while building a C++ program with custom includes using VS Code tasks


I'm trying to compile a C++ program "test.cpp" that includes a custom file "Cars.h" using VS Code. However it causes a build error even though I'm pretty sure I did everything right.

My directory structure:

Test
├── .vscode
│   ├── tasks.json
├── include
│   ├── Cars.cpp
│   └── Cars.h
├── test.cpp

test.cpp

#include <iostream>
#include "include/Cars.h"

using namespace std;

int main(){
    Cars c;
    cout << "Hello!" << endl;
    c.printcars();  
}      

Cars.cpp

#include <iostream>

class Cars{

    public:
        void printcars(){
            std::cout << "Cars" << std::endl;
        }

};

Cars.h

#ifndef CARS_H
#define CARS_H

class Cars {
    public:
        void printcars();

};

#endif

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "buildFile",
            "command": "g++",
            "args": [
                "-o",
                "${fileBasenameNoExtension}.exe",
                "${file}",
                "${workspaceFolder}\\include\\*.cpp",
                "${workspaceFolder}\\include\\*.h",
                "-I${workspaceFolder}\\include"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
        
    ]
}

Error:

test.cpp:(.text+0x37): undefined reference to `Cars::printcars()'
collect2.exe: error: ld returned 1 exit status

Build finished with error(s).

 *  The terminal process terminated with exit code: -1. 
 *  Terminal will be reused by tasks, press any key to close it. 

I am certain that it's a linker error, since the program runs perfectly when I include Cars.cpp instead of Cars.h. However this is a test and I am required to include the header file only.


Solution

  • There's a few things wrong. But the main one is that you have defined the class Cars twice, once in cars.h and once in cars.cpp.

    cars.cpp should look like this

    #include <iostream>
    #include "cars.h"
    
    void Cars::printcars(){
        std::cout << "Cars" << std::endl;
    }
    

    Don't define Cars twice, instead include cars.h in cars.cpp and use an out of class definition for Cars::printcars.

    The other thing I don't like is your tasks.json file. Don't use ${file}, that is the file you are currently editing. I'm sure you can see that might cause problems, you can only build your code if you happen to be editing main.cpp. Secondly don't compile header files, so remove "${workspaceFolder}\\include\\*.h"

    Something like

            "args": [
                "-o",
                "${fileBasenameNoExtension}.exe",
                "${workspaceFolder}\\main.cpp",
                "${workspaceFolder}\\include\\*.cpp",
                "-I${workspaceFolder}\\include"
            ],
    

    seems right to me (but I'm no expert on VSCode).