0

I have two sources file, main.cpp & functions.cpp, and a header filed main.h, and finally a Makefile:

main.cpp

#include "main.h"

int main()
{
    Application game;

    game.update();
    game.draw();
}

functions.cpp

#include "main.h"

Application::Application()
{
    window = SDL_CreateWindow("SDL GAME", 
            SDL_WINDOWPOS_CENTERED, 
            SDL_WINDOWPOS_CENTERED, 
            SCREEN_WIDTH, 
            SCREEN_HEIGHT, 0);

    if(!window)
    {
        printf("Error: %s\n", SDL_GetError());
    }

    windowSurface = SDL_GetWindowSurface(window);

    if(!windowSurface)
    {
        printf("Error: %s\n", SDL_GetError());
    }
}

Application::~Application()
{
    SDL_FreeSurface(windowSurface);
    SDL_DestroyWindow(window);
}

void Application::update()
{
    bool quit = false;
    while(!quit)
    {
        SDL_Event e;
        while(SDL_PollEvent(&e) > 0) //Event queue
        {
            switch(e.type)
            { //Add events here
                case SDL_QUIT:
                    quit = true;
                    break;
            }
        }
        //DRAW
        Application::draw();
        //STOP DRAW
        SDL_UpdateWindowSurface(window);
    }
}

void Application::draw()
{
    SDL_UpdateWindowSurface(window);
}

main.h

#pragma once

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include <string>

const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;




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

        void update();
        void draw();

    private:
        SDL_Window *window = NULL;
        SDL_Surface *windowSurface = NULL;
        SDL_Event event;
};

Makefile

.PHONY = all clean

CC = g++

SRCS:= $(wildcard src/*.cpp) # Succesfully grabs all source files
BINS := $(SRCS:%.cpp=%)

LINKERFLAG = -lSDL2 -Isrc


all: ${BINS}

%: %.cpp
    ${CC} ${LINKERFLAG} $< -o [email protected]

%.o: %.cpp
    ${CC} -o $<.o

clean:
    rm -rvf *.o ${BINS}

The error

g++ -lSDL2 -Isrc src/main.cpp -o src/main.o /usr/lib64/gcc/x86_64-suse-linux/10/../../../../x86_64-suse-linux/bin/ld: /tmp/ccp2ZmwE.o: in function main': main.cpp:(.text+0x11): undefined reference to Application::Application()' /usr/lib64/gcc/x86_64-suse-linux/10/../../../../x86_64-suse-linux/bin/ld: main.cpp:(.text+0x1d): undefined reference to Application::update()' /usr/lib64/gcc/x86_64-suse-linux/10/../../../../x86_64-suse-linux/bin/ld: main.cpp:(.text+0x29): undefined reference to Application::draw()' /usr/lib64/gcc/x86_64-suse-linux/10/../../../../x86_64-suse-linux/bin/ld: main.cpp:(.text+0x35): undefined reference to Application::~Application()' /usr/lib64/gcc/x86_64-suse-linux/10/../../../../x86_64-suse-linux/bin/ld: main.cpp:(.text+0x4b): undefined reference to Application::~Application()'


What I have tried: using -c to compile all then running again without to link, no success. I'm coming to c++ and Make from a python background so it is fairly new to me. What I think is happening is it's trying to link main.cpp before compiling functions.cpp, but I don't know how to go about that figuring that out.

2
  • 1
    My make is rusty so I can't be of much actual help, but one approach you could take is to not wildcard everything up front. Be more explicit first and generalize if needed. Commented Mar 31, 2021 at 3:10
  • So that worked but now I'm just curious why my current makefile doesn't work. Does un-generalizing count as a solution? Commented Mar 31, 2021 at 3:20

1 Answer 1

1

Suppose you have a self-contained source file, foo.cpp.

You could build the executable foo in one step:

g++ foo.cpp -o foo

Or you could build the object file, then build the executable from that:

g++ -c foo.cpp -o foo.o
g++ foo.o -o foo

Now suppose you have two source files, main.cpp and functions.cpp. The code in main.cpp calls a function defined in functions.cpp. If you carelessly try to build the executable from only one file:

g++ main.cpp -o app

the compiler will complain that your code calls a function that has no definition. This is what your makefile does, when it tries to build main:

%: %.cpp
    ${CC} ${LINKERFLAG} $< -o [email protected]

The usual way in a case like this is to build the object files first, then link them:

g++ -c main.cpp -o main.o
g++ -c functions.cpp -o functions.o
g++ main.o functions.o -o name_of_executable

You can do that with a makefile that looks like this:

$(EXEC_NAME): main.o functions.o
    ${CC} ${LINKERFLAG} $^ -o $@

%.o: %.cpp
    ${CC} -c $< -o $@

There are some more refinements to make (and you don't even have to write that second rule, Make already knows it), but that should be enough to get you started.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.