SOLVED - Makefile: Multiple Definition of Function (Actually a C++ lesson) - c++

I'm trying to write more sophisticated makefiles, but my explorations have gotten me into a multiple definition issue.
The program is meant to brute-force a marble maze, so I have a class for the game board declared in marbleBoard.h, with its implementation written in marbleBoard.cpp. The .cpp file #includes the .h file. The main program is written in marble.cpp. The Variables NORTH, SOUTH, EAST, and WEST refer to bit masks that symbolize walls, and are defined in marbleBoard.h outside of the class.
I based my makefile on MrBook's tutorial Makefiles.
Here is the Makefile code:
#!/bin/bash
COMPILER=g++
CFLAGS=-c -g -std=c++14
all: marble
marble: marble.o marbleBoard.o
$(COMPILER) marble.o marbleBoard.o -o marble
marble.o: marble.cpp
$(COMPILER) $(CFLAGS) marble.cpp
marbleBoard.o: marbleBoard.cpp marbleBoard.h
$(COMPILER) $(CFLAGS) marbleBoard.cpp marbleBoard.h
clean:
rm *o marble
This is the output I recieve:
[uthranuil#Palantir marble]$ make
g++ -c -g -std=c++14 marbleBoard.cpp marbleBoard.h
g++ marble.o marbleBoard.o -o marble
marbleBoard.o:(.data+0x0): multiple definition of `NORTH'
marble.o:(.data+0x0): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `EAST'
marble.o:(.data+0x1): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `SOUTH'
marble.o:(.data+0x2): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `WEST'
marble.o:(.data+0x3): first defined here
collect2: error: ld returned 1 exit status
make: *** [makefile:10: marble] Error 1
I have spent a lot of time looking for answers and trying different solutions. Here is a list of Q/As I have read:
Function multiple definition linker error building on GCC - Makefile issueMakefile: multiple definition and undefined reference errorMakefile: multiple definition of TMC_ENDError in makefile: multiple definition of _startmultiple definition errors when using makefile
Any help is greatly appreciated. Thank you for your time and attention.

Related

Multiple definition of variable First defined here error

I have this c++ project with classes' definitions inside .hpp files and methods' declarations inside .cpp files.
The project uses a makefile to build and run.
The program ran without errors before but LinkedList didn't work as I wanted so I re-wrote it entirely.
Now LinkedList.hpp includes both the class definition and its methods' declarations.
I adjusted the other classes' methods so that they use LinkedList correctly.
Now when debugging the program I get this multiple definition of, first defined here error.
find: ‘lib’: No such file or directory
g++ -std=c++17 -Wall -Wextra -g -Iinclude -o output/main src/Game.o src/Hero.o src/Title.o src/Level.o src/Menu.o src/Entity.o src/Window.o src/main.o src/Map.o src/Object.o -lncurses
/usr/bin/ld: src/Hero.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: multiple definition of `TileTypeStr'; src/Game.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: first defined here
/usr/bin/ld: src/Level.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: multiple definition of `TileTypeStr'; src/Game.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: first defined here
/usr/bin/ld: src/Entity.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: multiple definition of `TileTypeStr'; src/Game.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: first defined here
/usr/bin/ld: src/Map.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: multiple definition of `TileTypeStr'; src/Game.o:/home/user/projects/project-X-githubClone/projectX/include/Object.hpp:2: first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:74: main] Error 1
So if I get this correctly, the problem is the multiple definitions of const char* TileTypeStr[].
But why then when I change that array's name to, say, tts the error message still reads "multiple definitions of TileTypeStr"?
and why if I comment out the only 2 references (including its declaration and initialisation) of this array inside the whole project the error message is still the same?
TileTypeStr[] was misplaced after all, moved it inside the toString() method I needed it for, then ran make clean to recompile all of the source files and make to build main.cpp.
By running make and not recompiling the source files I was stuck running the bugged version of the program.

Trying to compile simple project that uses TRI DDS using cygwin gcc

I am trying to take the TRI DDS example code. It is all setup to build with MSVS2012 and comes with MSVS2012 proj/solution files.
However I want to try to build this using Cygwin and g++/gcc. I have got so far and then hit issues.
My cpp/h files are taken from their example - the user code is basic c++ but the generated files / RTI DDS files I think are causing an issue.
The basic source files are:
Hello.cpp
HelloPublisher.cpp/h
HelloSubscriber.cpp/h
HelloWorld.idl
RTI-DDS generator uses HelloWorld.idl to generate further files (.cxx/h files). I am not expecting to change any of the RTI-DDS files and the code within the 4 source files are fairly vanilla, so I can compile them if I hack out all the calls to RTI-DDS.
The area I want to focus on is the makefile / environment. Here are the pertinent parts of my makefile (note the linker parts are not complete because I have not got that far yet - the compile still fails):
note NDDSHOME = c:\Program Files\rti_connext_dds-5.3.0 as an env var.
# Setup minimal "un-polluted" paths to try to avoid any conflicts
makePaths=/usr/local/bin:/usr/bin:$(NDDSHOME)/bin
export PATH := $(makePaths)
#Include Paths
INCLUDES = -I. -I"$(NDDSHOME)/include" -I"$(NDDSHOME)/include/ndds" -I"$(NDDSHOME)/include/ndds/hpp"
#Compiler / options:
DEFINES = -DRTI_WIN32 -DRTI_STATIC -DWIN32 -D_WIN32_WINNT=_WIN32_WINNT_WIN7
CC = g++
CC_FLAGS = -std=c++11 -Wall -Wextra -lWS2_32
EXEC = run
# C++ files
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES.cpp=.o)
# Main Target
$(EXEC): $(OBJECTS)
# Don't do linking yet - compile not working!
%.o: %.cpp
$(CC) $< -o $# -c $(DEFINES) $(CC_FLAGS) $(INCLUDES)
I know the INCLUDES paths are working because I get different errors when they are not (can't find...)
But the error I get at the moment is:
/usr/include/w32api/winsock2.h:1004:68: error: conflicting declaration of c function 'int gethostname(char*, int)'
:
:
/usr/include/sys/unistd.h:268:6 note: previous declration 'int gethostname(char *, size_t)'
note I have to copy this by hand from my other PC... so I have abbreviated the complete message.
I thought I was close to solving this by looking at other questions with similar errors, but I can't quite make the connection to fix this. I have tried adding other defines to specify the windows version, but that did not fix it. I know there is a linker option that we need to use for things like mingw that is what the -lws2_32 flag is set for - but I have not got to the linker stage yet :(
I guess either the unistd.h or the winsock2.h should not really both be included, but I can't quite figure out what define (or other) I need to add...
Any ideas?

Deleting *.cpp file after compiling with wrong flag order?

I really need your help on this one!
I had a problem with my makefile. The error was very common:
makefile:11: recipe for target 'exec' failed
My makefile looks like this:
CC = g++
PY = python
FLAGS = -std=c++11 -O3
all: main exec data
main: main.cpp
$(CC) $(FLAGS) -o $# $<
exec: main
time ./$<
data: plot.py main
$(PY) $<
As far as im concerned there is no mistake but I still got the error, maybe main.cpp was not compiled?
Anyway I then tried (out of curiosity):
g++ -std=c++11 -O3 -o main.cpp main
And then I got this error:
main: In function `_start':
(.text+0x1360): multiple definition of `_start'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.text+0x0): first defined here
main: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crti.o:(.fini+0x0): first defined here
main:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.rodata.cst4+0x0): first defined here
main: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.data+0x0): first defined here
main:(.rodata+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/crtbegin.o:(.rodata+0x0): first defined here
main: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crti.o:(.init+0x0): first defined here
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
main:(.data+0x8): first defined here
/usr/bin/ld: error in main(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
And now my main.cpp is gone. What the actual.. How can I recover it? I have an older version of it because I'm using git, but its rather unfinished and I really need this version.
The error was very common
That's the make error. What did it show before that? Did it run the compiler at all? Was there a compile error? What was it?
I addressed your proximate problem below, but the original issue is the compile error. You're fixating on the fact that a build target failed, rather than on understanding why it failed.
Builds fail all the time: very commonly because there's a mistake in the code, and very rarely because of an error in a previously-working makefile. As a consequence, you usually want to worry about understanding and fixing the compiler error, before you start changing your makefile or running the compiler manually.
And now my main.cpp is gone. What the actual..
Well, in
g++ -std=c++11 -O3 -o main.cpp main
the option -o filename tells g++ to use filename for output. So, it opened main.cpp for output and clobbered the contents.
You meant
g++ -std=c++11 -O3 -o main main.cpp
It's an easy mistake to make, which is why we have build systems to do this stuff for us. And backups. And version control.
In future, you can just type make main to select a single target, and make should tell you what it's doing.
How can I recover it?
From your editor, or version control, or backup, or filesystem-level snapshotting if you have a fancy SAN or, in extremis, from memory.
Nothing teaches good source control and backup habits like having to rewrite something from scratch.
there is no main.cpp file anymore. why exactly is that?
When the build failed, the incomplete output file was deleted.
Consider, for reference, how make works. You have a target called main, so it checks whether a file called main exists.
if main exists, it looks at the dependencies, and sees if any of those files are newer then main
if it thinks main should be (re-)generated (either it doesn't exist or is older than a dependency), it runs the rule you gave it
Now if g++ left an empty (or incomplete) version of main lying around after a failed compilation, how would make know to re-generate it the next time you built?
It's essential that the output file be deleted when compilation fails, because otherwise make wouldn't work correctly. You'd also have a directory full of empty or corrupt partly-compiled executables and object files, which doesn't sound like such a great idea.
In other news, your exec target doesn't create a file called exec. This should be a .PHONY rule. So, probably, should data.
The problem is:
g++ -std=c++11 -O3 -o main.cpp main
Where you specify that the output should be placed in main.cpp. You try to compile main and store the result in main.cpp. Since the compile failed, the output file is removed after compilation stopped. So no main.cpp.
It's simple: Just save the file again in your editor.
To do so, press C-x C-w and type the filename again.

Problem in building my own module in omnetpp

I'm trying to write an application using the UDP module included
in the inetmanet framework in omnetpp. The problem is that the files that I have to include don't get included in the linking phase.
The errors are:
opp_makemake
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$ opp_makemake --deep -f -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base
Creating Makefile in /home/bedo/omnetpp/samples/Basic-Broadcast-Simulation...
Makefile created, running "make depend" to add dependencies...
opp_makedep -Y --objdirtree -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base -I. -Igcc-debug -Igcc-debug/src -Igcc-debug/src/flooding -Isimulations -Isimulations/bitmaps -Isimulations/results -Isrc -Isrc/flooding -f Makefile -P\$O/ -- ./*.cc gcc-debug/*.cc gcc-debug/src/*.cc gcc-debug/src/flooding/*.cc simulations/*.cc simulations/bitmaps/*.cc simulations/results/*.cc src/*.cc src/flooding/*.cc
make
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$ make
g++ -c -g -Wall -fno-stack-protector -DHAVE_PCAP -DXMLPARSER=libxml -DWITH_PARSIM -DWITH_NETBUILDER -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base -I. -Igcc-debug -Igcc-debug/src -Igcc-debug/src/flooding -Isimulations -Isimulations/bitmaps -Isimulations/results -Isrc -Isrc/flooding -I/home/bedo/omnetpp/include -o out/gcc-debug//src/flooding/Flooding.o src/flooding/Flooding.cc
src/flooding/Flooding.cc: In member function ‘virtual void Flooding::handleLowerMsg(cMessage*)’:
src/flooding/Flooding.cc:82: warning: unused variable ‘m’
g++ -Wl,--export-dynamic -Wl,-rpath,/home/bedo/omnetpp/lib -Wl,-rpath,. -o out/gcc-debug//Basic-Broadcast-Simulation out/gcc-debug//src/flooding/Flooding.o -Wl,--whole-archive -Wl,--no-whole-archive -L"/home/bedo/omnetpp/lib/gcc" -L"/home/bedo/omnetpp/lib" -u _tkenv_lib -lopptkenvd -loppenvird -lopplayoutd -u _cmdenv_lib -loppcmdenvd -loppenvird -loppsimd -ldl -lstdc++
out/gcc-debug//src/flooding/Flooding.o: In function `Flooding::setupLowerLayer()':
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:50: undefined reference to `UDPControlInfo::UDPControlInfo()'
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:52: undefined reference to `UDPSocket::generateSocketId()'
out/gcc-debug//src/flooding/Flooding.o: In function `Flooding::sendMessage()':
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:101: undefined reference to `UDPControlInfo::UDPControlInfo()'
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:103: undefined reference to `IPAddress::ALL_HOSTS_MCAST'
collect2: ld returned 1 exit status
make: *** [out/gcc-debug//Basic-Broadcast-Simulation] Error 1
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$
I really don't know why they get included, and my module compile fine, but in the linking phase I get "undefined reference".
Any idea?
You can run nm on on all libraries you link with to see which library undefined symbols like this:
nm liboppcmdenvd.(so/a) | c++filt | grep UDPControlInfo
(c++filt demangles C++ symbols).
Library that requires the symbol will get output something like (U for Undefined):
00000000007f90a0 U UDPControlInfo
Library that defines/has the symbol will get output something like:
00000000007f90a0 T UDPControlInfo
This can be T or t
Of course, libraries you link with are indicated by arguments with starting by -l:
-lopptkenvd -loppenvird -lopplayoutd -u _cmdenv_lib -loppcmdenvd -loppenvird
liboppcmdenvd liboppenvird liboppsimd libUDPControlInfo
Solved. I modified the makefile in the root directory to a simpler one, leaving all the compile and linking duties to the src's makefile.
Thanks everyone

Compiling on Windows and Mac with Autotool

I have a problem trying to use autotools for a simple contrived project, the task is simple, use Objective-C on Mac OSX, and C++ on Windows (mingw) - with some C glue in the middle.
The project is structured like so (minus all the automatically generated files):
./aclocal.m4
./configure
./configure.ac
./Makefile.am
./src/darwin/greet.m
./src/greet.h
./src/main.cpp
./src/Makefile.am
./src/mingw32/greet.cpp
The contents of the key files are here on github in a gist. (didn't want to spam here)
I'm using the following command between changes:
$ autoreconf -vis && ./configure && make
The error I receive is full output (here in another gist):
....
Making all in src
g++ -g -O2 -o greetings main.o
Undefined symbols:
"greet()", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[1]: *** [greetings] Error 1
make: *** [all-recursive] Error 1
I'm very new to autotools, and have come a long way with the help of a couple of good people on IRC, but I think I'm making a conceptual mistake here, really hope there's a simple mistake I am making.
It was my understanding from the docs that EXTRA_progname_SOURCES should contain all possible files, and that the conditionals which are setup should work to select the correct ones.
Alarmingly, I don't think my makefiles are being remade, because even when I change the line in src/Makefile.am to include the sources explicitly for my platform (which is Max OS X Darwin, most of the time) -- the output remains completely the same.
I see that you're referring to greet.mm in the gist, but greet.m in the question. Automake does not appear to natively support Objective-C++ code. For Objective-C code, you need to have AC_PROG_OBJC in your configure.ac. If you really meant Objective-C++ code, you'll need to do this via a suffix rule.
g++ -g -O2 -o greetings main.o
This line tries to build greetings executable from main.o. If greet() function is defined in some other file, for example, greet.cpp, it should be:
++ -g -O2 -o greetings main.o greet.o
Possibly, this line from Makefile.am
greetings_SOURCES = main.cpp greet.h
should be something like this:
greetings_SOURCES = main.cpp greet.cpp
In Makefile.am you have:
if OS_DARWIN
greetings_SOURCES += darwin/greet.mm
endif
if OS_MINGW32
greetings_SOURCES += mingw32/greet.cpp
endif
This is the place which is not executed properly. You need to check it.