Problem background:
gcc v 4.1
2 .cpp files, 2 .h files

Files:
main.cpp
a.cpp
a.h
b.h

Organization:
main.cpp includes a.h (because it calls a.cpp code)
a.cpp includes a.h
a.h includes b.h (because a class in a.h uses a b.h class)
There is no inheritance between a.h or b.h or any of the classes.

The problem is that when I try to compile the files like
g++ main.cpp a.cpp
I get an bunch of linker errors like "duplicate symbol X found..." which are for symbols from b.h

Normally I would think this is due to there not being #ifndef or #pragma once guards, but there are "#pragma once" things at the top of all the .h files. To me it seems like what is happening is that gcc is generating main.o separately from a.o and then then ld is called it sees duplication of symbols and it errors out. What is the correct way to tell g++ to compile them both while looking at them both?

I would think it would be something like --combine, but the man page and testing show that's only valid for C files.
I have also tried -shared which makes ld not complain but which says it's for making a shared library, so it doesn't seem correct for building an executable. Will using -shared lead to any strange behavior down the road (I need to know now since the application itself isn't in a state that I can test it, and I don't want to end up finding out it was the -shared flag's fault)
I have also tried -fwhole-program, which again works, but the man page says it's for optimization, so that also doesn't seem correct. Same question with regards to possible weird behavior down the road.

Thanks much for any help.

John

Dani AI

Generated

As hinted, this is almost always caused by definitions that live in a header (b.h) rather than just declarations. Include guards or #pragma once prevent multiple inclusion inside a single translation unit, but they do not stop the same header from being compiled into more than one object file — so any non-inline function definitions or non-extern variable definitions in a header will be emitted into every .o that includes it and cause duplicate-symbol link errors.

Correct patterns (move definitions to a single .cpp, keep declarations in the header). Example: declare globals in the header, define them once in a .cpp:

// b.h
#ifndef B_H
#define B_H

struct B { /*...*/ };

extern int global_counter;   // declaration only

#endif
// b.cpp
#include "b.h"
int global_counter = 0;      // single definition

Allowed in headers: inline functions, templates, class definitions, and (since C++17) inline variables. Pre-C++17 global variables must use extern in headers and a single definition in one .cpp. Class static data members must also get one out-of-class definition in a .cpp.

Proper build workflow (debugging tip: compile to .o first and inspect symbols):

g++ -c main.cpp
g++ -c a.cpp
g++ main.o a.o -o myprog
# or: g++ main.cpp a.cpp -o myprog  (works when code is correct)
nm main.o | grep SOME_SYMBOL   # inspect where symbols come from

Avoid using flags like -shared or -fwhole-program to silence the linker: they change how objects are produced or optimized and only mask the real problem. Checklist: search headers for non-inline function bodies, non-extern globals, or definitions of static class members; move those definitions to a single .cpp or mark appropriately (inline/templates) and recompile. If duplicate symbols persist, post the offending header and the exact symbol names for a targeted diagnosis.

>>I get an bunch of linker errors like "duplicate symbol X found..." which are for symbols from b.h

That indicates there are errors in the header files -- you are compiling the *.cpp files correctly. Post the header file, you probably have an object declared in it without the extern keyword.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.