c++makefilecompiler-errorscompilationmingw32

Makefile Compilation Fails When Looking for Library Files, but Only When #include Is Located in Header File


I'm trying to make a minimal reproducible example file to show this problem off- this is how it works and what I am trying to do.

I am attempting to write the word "Applesauce" to a SFML window. There are 4 of my custom-written files- main.cpp, source.cc, header.hpp, and the Makefile. This is what they look like:

main.cpp:

#include "header.hpp"

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "My window");
    sf::Font font;
    font.loadFromFile("arial.ttf");

    sf::Text text;
    text.setFont(font);
    text.setString(get_string());
    text.setCharacterSize(24);
    text.setFillColor(sf::Color::Red);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(text);
        window.display();
    }

    return 0;
}

header.hpp:

#ifndef HEADER_H
#define HEADER_H

#include <iostream>
#include <SFML/Graphics.hpp>

std::string get_string();

#endif // HEADER_H

source.cc:

#include "../header.hpp"

std::string get_string() {
    return "Applesauce";
}

Makefile:

# Compiler
CC=g++

# Flags for the C++ compiler
CXXFLAGS=-Wall -Wextra -pedantic -std=c++17

# Include directory for SFML and the header files for your project
INCLUDE=-Isrc -Isrc/include -Iscripts

# Libraries to link against
LIBS=-L src/lib -l sfml-graphics -l sfml-window -l sfml-system

# List of source files
SRCS=main.cpp scripts/source.cc

# List of object files
OBJS=$(patsubst %.cpp,%.o,$(SRCS))

# Executable file to create
EXEC=applesauce

all: $(EXEC)

$(EXEC): $(OBJS)
    $(CC) $(OBJS) -o $(EXEC) $(LIBS)

main.o: main.cpp 
    $(CC) $(CXXFLAGS) $(INCLUDE) -c main.cpp -o main.o

scripts/source.o: scripts/source.cc 
    $(CC) $(CXXFLAGS) $(INCLUDE) -c scripts/source.cc -o scripts/source.o

clean:
    rm -f $(EXEC) $(OBJS)

However, when trying to compile the code, I get thrown an error- the Makefile is unable to locate the <SFML/Graphics.hpp> file:

PS C:\Users\[My Windows User Name]\Documents\C++ Visual Studio Projects\Headers and Scripts and SFML v4> mingw32-make
g++ main.o scripts/source.cc -o applesauce -L src/lib -l sfml-graphics -l sfml-window -l sfml-system
In file included from scripts/source.cc:1:
scripts/../header.hpp:5:10: fatal error: SFML/Graphics.hpp: No such file or directory
 #include <SFML/Graphics.hpp>
          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
mingw32-make: *** [Makefile:25: applesauce] Error 1

An interesting fact is that when I instead have the #include <SFML/Graphics.hpp> line in main.cpp, the program compiles perfectly fine. This is odd because main.cpp and header.hpp are located in the same directory and I just don't quite understand why it can locate the file in one scenario but not the other.

I'm trying to have #include <SFML/Graphics.hpp> in header.hpp because I plan on (in my actual program) having functions that require the SFML libraries inside of .cc files.

Any help is vastly appreciated- thank you very much!


Solution

  • The problem is in these two lines:

    # List of source files
    SRCS=main.cpp scripts/source.cc
    
    # List of object files
    OBJS=$(patsubst %.cpp,%.o,$(SRCS))
    

    Because you substitute .cpp but not .cc, the file scripts/source.cc gets included in the build for the executable and thus without the correct flags, as shown by make's display of the command:

    g++ main.o scripts/source.cc -o applesauce -L src/lib -l sfml-graphics -l sfml-window -l sfml-system