|
|
|||
Makefiles
Hello,
As I continue in my programming education, my programs are becoming increasingly large and complex. As a result I decided to start to learn how to write makefiles. I wrote one up for project I'm working on. It had two header files and three .cpp files. When I went to make, I got a boatload of errors, such as methods already defined. I put all the .cpp files into one file, and it works fine. What gives? I can get away with one large .cpp file in this project, but my next one (final project) will be too large for one file. I do have ifndef, defines for the header files. And each .cpp file called both header files. I don't know if that matters or not. Here is the Makefile I wrote (didn't work - it did when it was reduced to one .cpp file): Code:
hack_slash: main.o draw.o collision.o g++ main.o draw.o collision.o -o hack_slash -lcurses main.o: main.cpp g++ -c main.cpp draw.o: draw.cpp g++ -c draw.cpp collision.o: collision.cpp g++ -c collision.cpp clean: rm *.o Here are the errors I received: Code:
g++ main.o draw.o collision.o -lcurses draw.o: In function `thing::thing()': draw.cpp:(.text+0x0): multiple definition of `thing::thing()' main.o:main.cpp:(.text+0x0): first defined here draw.o: In function `thing::thing()': draw.cpp:(.text+0x6): multiple definition of `thing::thing()' main.o:main.cpp:(.text+0x6): first defined here draw.o: In function `thing::thing(int, int, char)': draw.cpp:(.text+0xc): multiple definition of `thing::thing(int, int, char)' main.o:main.cpp:(.text+0xc): first defined here draw.o: In function `thing::thing(int, int, char)': draw.cpp:(.text+0x34): multiple definition of `thing::thing(int, int, char)' main.o:main.cpp:(.text+0x34): first defined here draw.o: In function `thing::getx()': draw.cpp:(.text+0x5c): multiple definition of `thing::getx()' main.o:main.cpp:(.text+0x5c): first defined here draw.o: In function `thing::gety()': draw.cpp:(.text+0x66): multiple definition of `thing::gety()' main.o:main.cpp:(.text+0x66): first defined here draw.o: In function `thing::get_symbol()': draw.cpp:(.text+0x72): multiple definition of `thing::get_symbol()' main.o:main.cpp:(.text+0x72): first defined here draw.o: In function `agent::agent(int, int, char)': draw.cpp:(.text+0x80): multiple definition of `agent::agent(int, int, char)' main.o:main.cpp:(.text+0x80): first defined here draw.o: In function `agent::agent(int, int, char)': draw.cpp:(.text+0xd8): multiple definition of `agent::agent(int, int, char)' main.o:main.cpp:(.text+0xd8): first defined here draw.o: In function `agent::get_velx()': draw.cpp:(.text+0x130): multiple definition of `agent::get_velx()' main.o:main.cpp:(.text+0x130): first defined here draw.o: In function `agent::get_vely()': draw.cpp:(.text+0x144): multiple definition of `agent::get_vely()' main.o:main.cpp:(.text+0x144): first defined here draw.o: In function `agent::set_alive(bool)': draw.cpp:(.text+0x158): multiple definition of `agent::set_alive(bool)' main.o:main.cpp:(.text+0x158): first defined here draw.o: In function `agent::wall_collide()': draw.cpp:(.text+0x170): multiple definition of `agent::wall_collide()' main.o:main.cpp:(.text+0x170): first defined here draw.o: In function `agent::wall_crash()': draw.cpp:(.text+0x21c): multiple definition of `agent::wall_crash()' main.o:main.cpp:(.text+0x21c): first defined here draw.o: In function `agent::get_alive()': draw.cpp:(.text+0x25e): multiple definition of `agent::get_alive()' main.o:main.cpp:(.text+0x25e): first defined here draw.o: In function `agent::get_prevx()': draw.cpp:(.text+0x26e): multiple definition of `agent::get_prevx()' main.o:main.cpp:(.text+0x26e): first defined here draw.o: In function `agent::get_prevy()': draw.cpp:(.text+0x2c4): multiple definition of `agent::get_prevy()' main.o:main.cpp:(.text+0x2c4): first defined here draw.o: In function `dot::dot(int, int, char)': draw.cpp:(.text+0x31c): multiple definition of `dot::dot(int, int, char)' main.o:main.cpp:(.text+0x31c): first defined here draw.o: In function `dot::dot(int, int, char)': draw.cpp:(.text+0x358): multiple definition of `dot::dot(int, int, char)' main.o:main.cpp:(.text+0x358): first defined here draw.o: In function `guard::guard(int, int, char)': draw.cpp:(.text+0x394): multiple definition of `guard::guard(int, int, char)' main.o:main.cpp:(.text+0x394): first defined here draw.o: In function `guard::guard(int, int, char)': draw.cpp:(.text+0x3ba): multiple definition of `guard::guard(int, int, char)' main.o:main.cpp:(.text+0x3ba): first defined here draw.o: In function `hackbot::hackbot(int, int, char)': draw.cpp:(.text+0x3e0): multiple definition of `hackbot::hackbot(int, int, char)' main.o:main.cpp:(.text+0x3e0): first defined here draw.o: In function `hackbot::hackbot(int, int, char)': draw.cpp:(.text+0x41c): multiple definition of `hackbot::hackbot(int, int, char)' main.o:main.cpp:(.text+0x41c): first defined here draw.o: In function `slashbot::slashbot(int, int, char)': draw.cpp:(.text+0x458): multiple definition of `slashbot::slashbot(int, int, char)' main.o:main.cpp:(.text+0x458): first defined here draw.o: In function `slashbot::slashbot(int, int, char)': draw.cpp:(.text+0x494): multiple definition of `slashbot::slashbot(int, int, char)' main.o:main.cpp:(.text+0x494): first defined here draw.o: In function `guard::get_distance(int, int, int, int)': draw.cpp:(.text+0x526): multiple definition of `guard::get_distance(int, int, int, int)' main.o:main.cpp:(.text+0x4d0): first defined here draw.o: In function `guard::normalize_local_steer(float)': draw.cpp:(.text+0x5a0): multiple definition of `guard::normalize_local_steer(float)' main.o:main.cpp:(.text+0x54a): first defined here draw.o: In function `guard::flee(int, int, float)': draw.cpp:(.text+0x616): multiple definition of `guard::flee(int, int, float)' main.o:main.cpp:(.text+0x5c0): first defined here draw.o: In function `guard::seek(int, int, float)': draw.cpp:(.text+0x68e): multiple definition of `guard::seek(int, int, float)' main.o:main.cpp:(.text+0x638): first defined here draw.o: In function `guard::arrive(int, int, float, float, float)': draw.cpp:(.text+0x70a): multiple definition of `guard::arrive(int, int, float, float, float)' main.o:main.cpp:(.text+0x6b4): first defined here draw.o: In function `agent::normalize_vel()': draw.cpp:(.text+0x838): multiple definition of `agent::normalize_vel()' main.o:main.cpp:(.text+0x7e2): first defined here draw.o: In function `agent::normalize_steer()': draw.cpp:(.text+0x8b2): multiple definition of `agent::normalize_steer()' main.o:main.cpp:(.text+0x85c): first defined here draw.o: In function `guard::wall_avoid(int, int, float)': draw.cpp:(.text+0x92c): multiple definition of `guard::wall_avoid(int, int, float)' main.o:main.cpp:(.text+0x8d6): first defined here draw.o: In function `guard::evade(int, int, float, float, float)': draw.cpp:(.text+0xa24): multiple definition of `guard::evade(int, int, float, float, float)' main.o:main.cpp:(.text+0x9ce): first defined here draw.o: In function `guard::pursue(int, int, float, float, float)': draw.cpp:(.text+0xb06): multiple definition of `guard::pursue(int, int, float, float, float)' main.o:main.cpp:(.text+0xab0): first defined here draw.o: In function `agent::update()': draw.cpp:(.text+0xbe8): multiple definition of `agent::update()' main.o:main.cpp:(.text+0xb92): first defined here draw.o: In function `slashbot::move(dot, hackbot, thing*)': draw.cpp:(.text+0xcb6): multiple definition of `slashbot::move(dot, hackbot, thing*)' main.o:main.cpp:(.text+0xc60): first defined here draw.o: In function `hackbot::move(dot, slashbot, thing*)': draw.cpp:(.text+0xd8a): multiple definition of `hackbot::move(dot, slashbot, thing*)' main.o:main.cpp:(.text+0xd34): first defined here draw.o: In function `dot::player_steer(int)': draw.cpp:(.text+0xe30): multiple definition of `dot::player_steer(int)' main.o:main.cpp:(.text+0xdda): first defined here collision.o: In function `thing::thing()': collision.cpp:(.text+0x0): multiple definition of `thing::thing()' main.o:main.cpp:(.text+0x0): first defined here collision.o: In function `thing::thing()': collision.cpp:(.text+0x6): multiple definition of `thing::thing()' main.o:main.cpp:(.text+0x6): first defined here collision.o: In function `thing::thing(int, int, char)': collision.cpp:(.text+0xc): multiple definition of `thing::thing(int, int, char)' main.o:main.cpp:(.text+0xc): first defined here collision.o: In function `thing::thing(int, int, char)': collision.cpp:(.text+0x34): multiple definition of `thing::thing(int, int, char)' main.o:main.cpp:(.text+0x34): first defined here collision.o: In function `thing::getx()': collision.cpp:(.text+0x5c): multiple definition of `thing::getx()' main.o:main.cpp:(.text+0x5c): first defined here collision.o: In function `thing::gety()': collision.cpp:(.text+0x66): multiple definition of `thing::gety()' main.o:main.cpp:(.text+0x66): first defined here collision.o: In function `thing::get_symbol()': collision.cpp:(.text+0x72): multiple definition of `thing::get_symbol()' main.o:main.cpp:(.text+0x72): first defined here collision.o: In function `agent::agent(int, int, char)': collision.cpp:(.text+0x80): multiple definition of `agent::agent(int, int, char)' main.o:main.cpp:(.text+0x80): first defined here collision.o: In function `agent::agent(int, int, char)': collision.cpp:(.text+0xd8): multiple definition of `agent::agent(int, int, char)' main.o:main.cpp:(.text+0xd8): first defined here collision.o: In function `agent::get_velx()': collision.cpp:(.text+0x130): multiple definition of `agent::get_velx()' main.o:main.cpp:(.text+0x130): first defined here collision.o: In function `agent::get_vely()': collision.cpp:(.text+0x144): multiple definition of `agent::get_vely()' main.o:main.cpp:(.text+0x144): first defined here collision.o: In function `agent::set_alive(bool)': collision.cpp:(.text+0x158): multiple definition of `agent::set_alive(bool)' main.o:main.cpp:(.text+0x158): first defined here collision.o: In function `agent::wall_collide()': collision.cpp:(.text+0x170): multiple definition of `agent::wall_collide()' main.o:main.cpp:(.text+0x170): first defined here collision.o: In function `agent::wall_crash()': collision.cpp:(.text+0x21c): multiple definition of `agent::wall_crash()' main.o:main.cpp:(.text+0x21c): first defined here collision.o: In function `agent::get_alive()': collision.cpp:(.text+0x25e): multiple definition of `agent::get_alive()' main.o:main.cpp:(.text+0x25e): first defined here collision.o: In function `agent::get_prevx()': collision.cpp:(.text+0x26e): multiple definition of `agent::get_prevx()' main.o:main.cpp:(.text+0x26e): first defined here collision.o: In function `agent::get_prevy()': collision.cpp:(.text+0x2c4): multiple definition of `agent::get_prevy()' main.o:main.cpp:(.text+0x2c4): first defined here collision.o: In function `dot::dot(int, int, char)': collision.cpp:(.text+0x31c): multiple definition of `dot::dot(int, int, char)' main.o:main.cpp:(.text+0x31c): first defined here collision.o: In function `dot::dot(int, int, char)': collision.cpp:(.text+0x358): multiple definition of `dot::dot(int, int, char)' main.o:main.cpp:(.text+0x358): first defined here collision.o: In function `guard::guard(int, int, char)': collision.cpp:(.text+0x394): multiple definition of `guard::guard(int, int, char)' main.o:main.cpp:(.text+0x394): first defined here collision.o: In function `guard::guard(int, int, char)': collision.cpp:(.text+0x3ba): multiple definition of `guard::guard(int, int, char)' main.o:main.cpp:(.text+0x3ba): first defined here collision.o: In function `hackbot::hackbot(int, int, char)': collision.cpp:(.text+0x3e0): multiple definition of `hackbot::hackbot(int, int, char)' main.o:main.cpp:(.text+0x3e0): first defined here collision.o: In function `hackbot::hackbot(int, int, char)': collision.cpp:(.text+0x41c): multiple definition of `hackbot::hackbot(int, int, char)' main.o:main.cpp:(.text+0x41c): first defined here collision.o: In function `slashbot::slashbot(int, int, char)': collision.cpp:(.text+0x458): multiple definition of `slashbot::slashbot(int, int, char)' main.o:main.cpp:(.text+0x458): first defined here collision.o: In function `slashbot::slashbot(int, int, char)': collision.cpp:(.text+0x494): multiple definition of `slashbot::slashbot(int, int, char)' main.o:main.cpp:(.text+0x494): first defined here collision.o: In function `guard::get_distance(int, int, int, int)': collision.cpp:(.text+0x6b0): multiple definition of `guard::get_distance(int, int, int, int)' main.o:main.cpp:(.text+0x4d0): first defined here collision.o: In function `guard::normalize_local_steer(float)': collision.cpp:(.text+0x72a): multiple definition of `guard::normalize_local_steer(float)' main.o:main.cpp:(.text+0x54a): first defined here collision.o: In function `guard::flee(int, int, float)': collision.cpp:(.text+0x7a0): multiple definition of `guard::flee(int, int, float)' main.o:main.cpp:(.text+0x5c0): first defined here collision.o: In function `guard::seek(int, int, float)': collision.cpp:(.text+0x818): multiple definition of `guard::seek(int, int, float)' main.o:main.cpp:(.text+0x638): first defined here collision.o: In function `guard::arrive(int, int, float, float, float)': collision.cpp:(.text+0x894): multiple definition of `guard::arrive(int, int, float, float, float)' main.o:main.cpp:(.text+0x6b4): first defined here collision.o: In function `agent::normalize_vel()': collision.cpp:(.text+0x9c2): multiple definition of `agent::normalize_vel()' main.o:main.cpp:(.text+0x7e2): first defined here collision.o: In function `agent::normalize_steer()': collision.cpp:(.text+0xa3c): multiple definition of `agent::normalize_steer()' main.o:main.cpp:(.text+0x85c): first defined here collision.o: In function `guard::wall_avoid(int, int, float)': collision.cpp:(.text+0xab6): multiple definition of `guard::wall_avoid(int, int, float)' main.o:main.cpp:(.text+0x8d6): first defined here collision.o: In function `guard::evade(int, int, float, float, float)': collision.cpp:(.text+0xbae): multiple definition of `guard::evade(int, int, float, float, float)' main.o:main.cpp:(.text+0x9ce): first defined here collision.o: In function `guard::pursue(int, int, float, float, float)': collision.cpp:(.text+0xc90): multiple definition of `guard::pursue(int, int, float, float, float)' main.o:main.cpp:(.text+0xab0): first defined here collision.o: In function `agent::update()': collision.cpp:(.text+0xd72): multiple definition of `agent::update()' main.o:main.cpp:(.text+0xb92): first defined here collision.o: In function `slashbot::move(dot, hackbot, thing*)': collision.cpp:(.text+0xe40): multiple definition of `slashbot::move(dot, hackbot, thing*)' main.o:main.cpp:(.text+0xc60): first defined here collision.o: In function `hackbot::move(dot, slashbot, thing*)': collision.cpp:(.text+0xf14): multiple definition of `hackbot::move(dot, slashbot, thing*)' main.o:main.cpp:(.text+0xd34): first defined here collision.o: In function `dot::player_steer(int)': collision.cpp:(.text+0xfba): multiple definition of `dot::player_steer(int)' main.o:main.cpp:(.text+0xdda): first defined here collect2: ld returned 1 exit status make: *** [hack_slash] Error 1
__________________
And the WORD was made flesh, and dwelt among us. (John 1:14) Last edited by JMJ_coder; 18th October 2008 at 03:25 PM. |
|
|||
Quote:
This is indicative that global variables and/or functions have been fully defined within header files. In general, this is a practice frowned upon for exactly the reasons presented. This problem only manifests itself when header files are included in multiple translation units which are ultimately linked together. Recall that a compiler will simply convert a compilation/translation unit into an object file. Since compilers do not retain any information from the compilation of one file to another, its understanding of the overall application is incomplete. On the other hand, the linker has to resolve all references made within an object file which are not defined within the object file itself. In other words, the linker has to tie everything together. If the linker sees multiple references to where global variables and/or functions are defined in multiple locations, the decision it will make is simply to abort since it is clear that the programmer is not aware of or has resolved the presence of duplicate definitions. Although not relevant to this particular issue, it is important to also recognize that linkers treat libraries differently. If the linker finds several libraries implementing function foo(), the linker will used the first occurrence found. What you should take away with this comment is that the order in which libraries are specified to the linker matters. |
|
|||
I don't see those two header files listed as dependencies in your Makefile.
If you prefer the BSD make you can do something like this Code:
# ------- See 'Make --- A Tutorial' by Adam de Boor (section 3.1) # in /usr/share/doc/psd/12.make (OpenBSD) OBJS = main.o draw.o collision.o .SUFFIXES : .ccp .o .ccp.o : g++ -c ${.IMPSRC} hack_slash : ${OBJS} g++ ${OBJS} -o ${.TARGET} -lcurses ${OBJS} : joe.h plumber.h
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump |
|
|||
Header files are not typically specified in Makefiles for the reasons I mentioned earlier. Header files should only contain function prototypes, structure declarations, & extern statements -- never executable code or variable definitions. Because Makefiles are concerned with compilation & linking, they typically only reference source code files.
|
|
|||
Quote:
The header files you create for your specific program form a dependency and thus should be listed as such in a Makefile rule. The only exception is Mr. Perfect Programmer, who writes his header file before everything else and never has to modify it.
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump |
|
|||
Of course. This was not the point of contention.
|
|
||||
As Ocicat pointed out it looks like you have put the class function definitions in the header file.
The header file must only contain the interface not the implementation. The textbook method to avoid the problem is to have a header and corresponding cc file for classes, eg. agent.h and agent.cc, with the func. def. in the latter file. |
|
|||
You weren't listening, it is necessary.. the compiler only links with libc, this is terminology you'll need to understand.
Let's take the prototype for printf for instance.. it's in stdio.h. Code:
int printf(const char *format, ...); This was a simple example, what you might want to do is read over the header files you're including.. it's most definitely beneficial to see what information they define. I'm not going to explain '...' (variable arguments), but you'll learn all this eventually yourself. |
|
||||
Not quite accurate mdh.
We usually call gcc through a front end (e.g. g++) which invokes the necessary programs to complete the indicated task. To compile, the front end has to parse the source files for the assembler. C, C++, and some dialects of Fortran get fed through a text pre processor first by default, which does not understand code. cpp the "C Pre Processor" knows nothing of C, it's as simple as sed s/search/replace/g for all most people need to care. The pre processed code is then parsed by the front end into the proper format and massaged into Register Transfer Language (RTL) by the back end. Which is then given to the the gnu assembler (as) for your platform, in order to create something that the GNU linker (ld) can understand. And eventually finding it's way into something that will be executed by your operating system. But most likely ocicats choice of words, were chosen to Keep It Simple for the Student. How much that's actually possible in C /or C++, I have no idea... lol.
__________________
My Journal Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''. Last edited by TerryP; 21st October 2008 at 09:33 PM. |
Tags |
make, makefile |
Thread Tools | |
Display Modes | |
|
|