MEGAEDIT 3000
I have discovered the cause of undefined references. I checked my .o files for symbols, and they were just missing. Just weren't there. For no apparent reason. I have checked the source of the compromiting .o file, but everything seemed to be OK. I've thought that it may be one of those nasty #ifdef ... #endif
blocks, cunningly hidden amongst lines of the code like a bear trap, waiting for its victim. But I couldn't find any. After moving some function definitions to the very end of the file and enclosing them in #ifdef ... #endif
block suitable for Linux, the symbols magically appeared and everything was fine. Thank you for your time.
Outdated, do not read.
I have been assigned to one big project lately, my job is to make it run on Linux platforms. Unfortunately, the programmer who wrote the whole project before me did a very poor job, creating whole lots of circular dependencies by including file
B3D_Base.h
, where almost every header is#included
, to almost every header and source file in the project (that makes 170+ files with#include "B3D_Base.h"
line). This caused no problems during compilation on both Windows and Linux. However, this causes lots of 'undefined reference' errors during linking phase on Linux, even though all object files and libraries are linked.
Being aware of ld
's limitation of single iteration through all object files during linking, I'm asking:
Is there a way to force ld
to do multiple iterations through objects and libraries, possibly solving all the 700+ undefined reference errors, or is my only chance to actually link the project just replacing all the #include "B3D_Base.h"
lines with proper includes to needed headers?
APPENDIX #1:
Here is an example of what mess I'm supposed to make run on Linux:
There is one header file B3D_Base.h
, to which is included B3D_Loading3.h
, which contains class B3D_LOADING3
. File B3D_Loading3.cpp
is including only B3D_Base.h
and a memory manager class not included in Base. An instance B3D_LOADING3 g_Loading3;
is declared in B3D_Base.h
and initializes+used in many other parts of the project. Everything compiles just fine, but when it comes to linking, I get many 'undefined reference to g_Loading3'
errors. And there are many more errors like this, complaining about undefined references to both class instances and functions alike. So much for clean code.
APPENDIX #2:
I'll be providing an SSCCE example, as kfsone requested:
B3D_Base.h
... (many other includes)
#include "B3D_Loading3.h"
extern B3D_LOADING3 g_Loading3;
... (includes go on)
B3D_Loading3.h/B3D_Loading.cpp
a full definition of class B3D_LOADING3, but no real declaration of g_Loading3
AW_Game.cpp (one of the files where g_Loading3 is used)
#include "B3D_Base.h"
... (some lines)
extern B3D_LOADING3 g_Loading3;
Thanks to kfsone who made me go through the code thoroughly, I managed to find out where the problem lies: g_Loading3 is defined everywhere as extern
, thus not being properly defined. All I needed was to remove the extern
keyword from one file. Fixed me ~ 30 linking errors. Thanks, kfsone.
APPENDIX #3:
But there is still problem with undefined references to class functions. After some code scanning, I suppose that the functions are not even defined due to overextended use of #ifdef ... #endif
clauses (portability) and thus it may be my fault, overlooking functions defined only in some passive ifdef block. I will try to look at this issue and later report if anything changed.
APPENDIX #3 REPORT:
Even after properly defining functions, the undefined-reference-list did not shrink. The problem is therefore still open for discussion.
APPENDIX #3.1
I'll be providing some example code.
Foo.h
#ifndef FOO_H
#define FOO_H
class Foo
{
unsigned int m_size;
bool m_lock;
friend class ASDF;
public:
unsigned int m_id;
void Release() {delete this;}
int Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags);
int Unlock();
};
// other class declarations to follow
#endif
Foo.cpp
#include "Foo.h"
// other includes and function definitions to follow
int Foo::Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags)
{
if(!m_lock)
{
// some locking code
}
return 0;
}
Baz.cpp
#include "Foo.h" // although included, defined and declared, causes undef reference
Foo *m_pFoo;
// several lines later
m_pFoo->Lock(0,0,(void)&Asdf,NULL); // <-- compiles fine, causes undefined reference
ld
doesn't provide such an option unfortunately. Are you using the same toolchain when building between windows and linux or is MSVC used for the former? – Talichcl /Za
disables microsoft's "extensions" to the C++ language. That might help catch more non-conformant c++ code. – Talichunittest
,test
or something to that effect. – Talich