0

I'm trying to build a c++ project in VS Code but when i try to build it g++ throws an error saying:

g++ -std=c++17 -ggdb -Iinclude src/main.cpp -o bin/main 
Undefined symbols for architecture x86_64:
  "MessageBus::MessageBus()", referenced from:
      _main in main-244f95.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [bin/main] Error 1
The terminal process "/bin/zsh '-c', 'make'" terminated with exit code: 2.

Here are the files that i think are causing the problem:

MessageBus.h

#pragma once
#include "../Utils/Queue.h"
#include "../Utils/SimpleList.h"
#include "Messages/Message.h"

class System;

class MessageBus
{
public:
    MessageBus();
    ~MessageBus();

    void addReciever(System* system);
    void postMessage(Message* msg);
    void notify();

private:
    Queue<Message> msgQueue;
    SimpleList<System*> systems;
};

MessageBus.cpp

#include "MessageBus.h"
#include "System.h"

MessageBus::MessageBus() {}
MessageBus::~MessageBus() {}

void MessageBus::postMessage(Message* msg) {
    msgQueue.add(msg);
}

void MessageBus::addReciever(System* system) {
    systems.add(system);
}

void MessageBus::notify() {
    int queueLength = msgQueue.getLength();
    for (int i = 0; i < queueLength; i++) {
        Message msg = msgQueue.pop();
        for (int j = 0; j < systems.getLength(); j++) {
            System* system = systems.get(j);
            system->handleMessage(&msg);
        }
    }
}

main.cpp

#include "EventSystem/MessageBus.h"

int main(int argc, char* argv[])
{
   MessageBus* msgBus = new MessageBus();
}

Makefile

CXX       := g++
CXX_FLAGS := -std=c++17 -ggdb

BIN     := bin
SRC     := src
INCLUDE := include

LIBRARIES   :=
EXECUTABLE  := main


all: $(BIN)/$(EXECUTABLE)

run: clean all
    clear
    ./$(BIN)/$(EXECUTABLE)

$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp
    $(CXX) $(CXX_FLAGS) -I$(INCLUDE) $^ -o $@ $(LIBRARIES)

clean:
    -rm $(BIN)/*

But when i try to compile these files together using the terminal:

g++ main.cpp EventSystem/MessageBus.cpp -o maintest

it works just fine, so i think the problem is that my files aren't compiled together. I think this might have something to do with the linker being unable to find the correct files and it might have something to do with my project structure? This is my current structure

As you can see the header files are located together with the source code. Should i separate the header files from the cpp files or is it that i have put them in subdirectories? Or is it something else entirely? I'm somewhat new to c++ and Makefiles and i can't seem to understand what is causing the problem.

Edit:

Solution:

As @MadScientist suggested i replaced $(SRC)/*.cpp in my Makefile with $(shell find $(SRC) -name \*.cpp -print) which solved the problem. But as @WhozCraig mentioned i should probably switch to cmake to avoid Makefiles in the future.

olbo98
  • 3
  • 2
  • Does this answer your question? [make for compiling — all \*.c files in folders & subfolders in project](https://stackoverflow.com/questions/19539422/make-for-compiling-all-c-files-in-folders-subfolders-in-project) – Michael May 13 '21 at 11:52
  • Please show the link command that make invoked, in your question. That's the most critical thing we need to see and you didn't show it. – MadScientist May 13 '21 at 11:55
  • 1
    Or use cmake and stop killing yourself with makefiles. Don't get me wrong; learning makefiles is a great asset; it's just also one that is less and less utilized with the advent of more modern project management tools. – WhozCraig May 13 '21 at 11:56
  • stop using Makefiles? What is the result of CMake? Makefiles – rioV8 May 13 '21 at 15:19

1 Answers1

2

You list the "working" command as:

g++ main.cpp EventSystem/MessageBus.cpp -o maintest

but your recipe is:

$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp

The glob expression $(SRC)/*.cpp won't match the file main.cpp.

If we could see your link line, we'd probably be able to see that main.cpp is missing.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • So should i change the glob expression then? I though $(SRC)/*.cpp would include all source files in the src directory. What should i change it to? – olbo98 May 13 '21 at 12:03
  • It will include all the source files in the `src` directory. But in your example link line, `main.cpp` is _NOT_ in the `src` directory. If that's really true, then that's your problem. If it's just a typo in your example, then please be careful with examples and use _cut and paste_ of all command lines, errors, etc. rather than retyping by hand. – MadScientist May 13 '21 at 12:14
  • Also, you have your other file in the directory `EventSystem`, not in the directory `src`. So that won't match either. – MadScientist May 13 '21 at 12:19
  • Oh, I think I see. Your directory structure is `src/EventSystem` and you have files `src/main.cpp` and `src/EventSystem/MessageBus.cpp`, and your example link line was invoked from within the `src` directory. So, it's really totally different. – MadScientist May 13 '21 at 12:20
  • The glob line `src/*.cpp` will match all `.cpp` files _in the src directory_. It's exactly identical to the files that are printed if you run `ls src/*.cpp` from your shell prompt. It won't match all source files in all subdirectories of the `src` directory. For that, you need to use either `$(SRC)/*/*.cpp` or you need to use something like `$(shell find $(SRC) -name \*.cpp -print)` – MadScientist May 13 '21 at 12:22
  • I opened the terminal and located to the src folder and invoked `g++ main.cpp EventSystem/MessageBus.cpp -o maintest` (this time i copy and pasted it). Are you saying the problem lies in the fact that the other source files are in subdirectories? – olbo98 May 13 '21 at 12:26
  • oh i see! I will try that – olbo98 May 13 '21 at 12:29
  • Just to note, you are not running make from inside the `src` directory. So showing us how a command would look from inside the `src` directory (without making clear that's what you did) as an example for how make should work, is certainly confusing. – MadScientist May 13 '21 at 14:25