2

I've started working with my first makefile. I'm writing a roguelike in C++ using the libtcod library, and have the following hello world program to test if my environment's up and running:

#include "libtcod.hpp"

int main()
{
    TCODConsole::initRoot(80, 50, "PartyHack");
    TCODConsole::root->printCenter(40, 25, TCOD_BKGND_NONE, "Hello World");
    TCODConsole::flush();
    TCODConsole::waitForKeypress(true);
}

My project directory structure looks like this:

/CppPartyHack  
----/libtcod-1.5.1 # this is the libtcod root folder  
--------/include  
------------libtcod.hpp  
----/PartyHack  
--------makefile  
--------partyhack.cpp # the above code  

(while we're here, how do I do proper indentation? Using those dashes is silly.)

and here's my makefile:


SRCDIR = .
INCDIR = ../libtcod-1.5.1/include
CFLAGS = $(FLAGS) -I$(INCDIR) -I$(SRCDIR) -Wall
CC = gcc
CPP = g++
.SUFFIXES: .o .h .c .hpp .cpp

$(TEMP)/%.o : $(SRCDIR)/%.cpp $(CPP) $(CFLAGS) -o $@ -c $< $(TEMP)/%.o : $(SRCDIR)/%.c $(CC) $(CFLAGS) -o $@ -c $<

CPP_OBJS = $(TEMP)partyhack.o

all : partyhack

partyhack : $(CPP_OBJS) $(CPP) $(CPP_OBJS) -o $@ -L../libtcod-1.5.1 -ltcod -ltcod++ -Wl,-rpath,.

clean : \rm -f $(CPP_OBJS) partyhack

I'm using Ubuntu, and my terminal gives me the following errors:

max@max-desktop:~/Desktop/Development/CppPartyhack/PartyHack$ make
g++ -c -o partyhack.o partyhack.cpp
partyhack.cpp:1:23: error: libtcod.hpp: No such file or directory
partyhack.cpp: In function ‘int main()’:
partyhack.cpp:5: error: ‘TCODConsole’ has not been declared
partyhack.cpp:6: error: ‘TCODConsole’ has not been declared
partyhack.cpp:6: error: ‘TCOD_BKGND_NONE’ was not declared in this scope
partyhack.cpp:7: error: ‘TCODConsole’ has not been declared
partyhack.cpp:8: error: ‘TCODConsole’ has not been declared
make: *** [partyhack.o] Error 1

So obviously, the makefile can't find libtcod.hpp. I've double checked and I'm sure the relative path to libtcod.hpp in INCDIR is correct, but as I'm just starting out with makefiles, I'm uncertain what else could be wrong. My makefile is based off a template that the libtcod designers provided along with the library itself, and while I've looked at a few online makefile tutorials, the code in this makefile is a good bit more complicated than any of the examples the tutorials showed, so I'm assuming I screwed up something basic in the conversion. Thanks for any help.

4 Answers 4

3

What happens here, is that

1) make evaluates the target all, which resolves to partyhack.

2) make evaluates the target partyhack, which resolves to $(CPP_OBJS)

3) make evaluates the target $(CPP_OBJS), which resolves to $(TMP)partyhack.o

4) make evaluates the target $(TMP)partyhack.o which resolves to partyhack.o

This is because TMP is not defined. Also note that the slash is missing after $(TMP).

5) make evaluates the target partyhack.o, and applies the implicit rule g++ -c -o partyhack.o partyhack.cpp

It does not apply the rule you specified, namely $(TEMP)/%.o : $(SRCDIR)/%.cpp because TEMP is not defined, so this evaluates to /partyhack.o : ./partyhack.cpp, and we are not building /partyhack.o because we are not in the root directory.

6) g++ does not find the include file, because the include directories were not passed to it, because your rule was not applied.

To fix this:

First, you need to define TEMP (see Nick Meyers answer).

TEMP = .

Second, you need to change the definition of CPP_OBJS (as Paul R suggested).

CPP_OBJS = %(TEMP)/partyhack.o

This will work if you invoke make inside the directory CppPartyHack/PartyHack.

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

2 Comments

Alright, these two changes worked. It still can't link, as it can't find ~ltcod++`, but that seems like a library issue and not a makefile issue, so I'll take this question to the libtcod forums. Thanks for your help, everyone.
Also, thanks for your step by step response, that was very helpful.
1

Make appears to be using a built-in rule as opposed to your custom rule for *.cpp files. (See the ordering of the -c and -o options in make's output -- it's not the same as the ones you wrote). Check the definition of your C++ file rule.

My best guess is that the references to $(TEMP) are throwing it off. Where is this defined?

Also note that for C++, usually the variables CXX and CXXFLAGS are used for the compiler program and the flags, respectively. CPP is used for the C preprocessor program, CPPFLAGS for preprocessor flags and CFLAGS is used for the C compiler flags. That's probably why make is not using your CFLAGS when using its built-in C++ rules.

4 Comments

Changing CFLAGS to CXXFLAGS and CPP to CXX helped. It still doesn't work, but it recognizes libtcod.hpp and TCODConsole now. It still reverses -c and -o, though, and now it can't find -ltcod++. About $(TEMP), I'm not sure where it's defined either, as it was part of the template makefile. I'll ask in the libtcod forums.
Yep, sounds like make is still not using your rule because TEMP is not defined (as @Paul R mentioned in his comment) and therefore the pattern in your rule "/%.o" doesn't match "partyhack.o". By the way, with make's built-in rules, LDFLAGS is used for linker flags like -L and -l. It doesn't hurt to stick to make's conventions even when writing your own rules -- it will make your makefiles easier to understand by others.
I've just started using makefiles, so I'm still unaware of convention. Where would I find these conventions?
@Max, the make manual (gnu.org/software/make/manual/make.html) is a good place to start.
0

Maybe you should change the INCDIR to an absolute path rather than a relative one? The current working directory may not be what you think it is while make is running.

1 Comment

Changing to an absolute path didn't change anything. Thanks for your answer, though.
0

There's obviously a problem somewhere because your CFLAGS definitions are not being passed to g++.

Change:

CPP_OBJS = $(TEMP)partyhack.o

to:

CPP_OBJS = $(TEMP)/partyhack.o

Other than that I don't see anything wrong.

2 Comments

The line originally had that backslash, but I was getting "Fatal error: can't create /partyhack.o: Permission denied". Removing the backslash seemed to fix that problem, but I suppose that was wrong?
It sounds like TEMP is not defined, so $(TEMP)/partyhack.o just expands to /partyhack.o. Maybe you should dump the use of TEMP for now and just focus on getting things working in the simplest way possible ? You can always refine it later...

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.