JStevens
JStevens

Reputation: 23

Multiple definition of function, why isn't the guard catching this?

So I wrote a small set of logging functions in the file cerus.h. The contents of that file can be seen below. It is being included in main.cpp, model.cpp, engine.cpp and camera.cpp. As can be seen, I have include guards so I'm not sure why I'm getting this error:

Output of $ make

jed@ArchPC:~/glPlayground$ make
g++ -std=c++11 -c model.cpp -o bin/model.o
g++ -std=c++11 -c tiny_obj_loader.cc -o bin/tinyobj.o
g++ -std=c++11 -c camera.cpp -o bin/camera.o
g++ -g -std=c++11 -o main bin/main.o bin/engine.o bin/tinyobj.o bin/model.o  bin/camera.o -lGL -lGLU -lglut -lSOIL -lGLEW -lglfw
bin/engine.o: In function `LOG(char const*)':
engine.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/engine.o: In function `LOGERR(char const*)':
engine.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
bin/model.o: In function `LOG(char const*)':
model.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/model.o: In function `LOGERR(char const*)':
model.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
bin/camera.o: In function `LOG(char const*)':
camera.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/camera.o: In function `LOGERR(char const*)':
camera.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'main' failed
make: *** [main] Error 1

cerus.h

#ifndef CERUS_H
#define CERUS_H
#include <iostream>
//Need to add Windows and Mac Includes here

// Linux Include Statements

void LOG(const char* str){
    std::cout << "[INFO]" << str << "\n";
}
void LOGERR(const char* str){
    std::cout << "[ERROR]" << str << "\n";
}

#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include <GLFW/glfw3.h>

#endif

Makefile

all: main

main: bin/main.o bin/engine.o bin/model.o bin/tinyobj.o bin/camera.o cerus.h
    g++ -g -std=c++11 -o main bin/main.o bin/engine.o bin/tinyobj.o  bin/model.o  bin/camera.o -lGL -lGLU -lglut -lSOIL -lGLEW -lglfw

bin/main.o: main.cpp cerus.h
    g++ -std=c++11 -c main.cpp -o bin/main.o

bin/engine.o: engine.cpp engine.h cerus.h
    g++ -std=c++11 -c engine.cpp -o bin/engine.o

bin/tinyobj.o: tiny_obj_loader.cc tiny_obj_loader.h cerus.h
    g++ -std=c++11 -c tiny_obj_loader.cc -o bin/tinyobj.o

bin/model.o: model.cpp model.h cerus.h
    g++ -std=c++11 -c model.cpp -o bin/model.o

bin/camera.o: camera.cpp camera.h cerus.h
    g++ -std=c++11 -c camera.cpp -o bin/camera.o

clean:
    rm -f bin/*.o main

If someone could explain to me why my guard isn't catching this, I would greatly appreciate the help.

EDIT: Fixed this issue by adding a file called cerus.cpp and defining my logging functions there instead of in cerus.h

Upvotes: 0

Views: 218

Answers (2)

xinaiz
xinaiz

Reputation: 7788

Guards did nothing wrong, they just protect your declarations/inlines/templates. It's the definitions that are real issue. If you have inline functions in your cpp, put them in header, same for templates. Do not include cpp files. Can't see much of your code but that is most of the cases.

Upvotes: 0

MikeCAT
MikeCAT

Reputation: 75062

This type of guard is to avoid things from being declared or defined in same translation unit.

It won't have any effect for multiple definition in different translation units (i.e. multiple source files).

In this case, you should move the definitions of functions LOG and LOGERR to another .cpp file, and put declarations of the functions in the header file.

Upvotes: 2

Related Questions