I'm compiling and linking a cpp file against a pre-compiled library, and I'm getting an "undefined reference" error.
Firstly, this is the command (the library in question is quicknet3, the program I'm compiling is trapper):
g++ -w -g -I. -g -O3 -pipe -Wall -I/home/install/x86_64/include/quicknet3 -L/home/install/x86_64/lib -lquicknet3 -lintvec -lfltvec -o trapper trapper.cpp CMyException.cpp
Here's the undefined reference error:
/tmp/ccFuVczF.o: In function 'main':
trapper.cpp:1731: undefined reference to 'QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int, char const*, _IO_FILE*, int)'
The call in trapper.cpp (line 1731) is:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", fp, 1);
where fp is a FILE *, assigned as the result of an fopen call beforehand.
The constructor being called is defined in the relevant header file (QN_Pfile.h), as follows:
class QN_InFtrLabStream_PFile : public
QN_InFtrLabStream
{
public:
QN_InFtrLabStream_PFile(int a_debug, const char* a_dbgname, FILE* a_file, int a_indexed);
(... other declarations ...)
}
The definition of the constructor is indeed given in QN_Pfile.cc:
QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int a_debug,const char* a_dbgname, FILE* a_file, int a_indexed) : log(a_debug, "QN_InFtrLabStream_PFile", a_dbgname),file(a_file),indexed(a_indexed),buffer(NULL),sentind(NULL)
{
(... the usual constructor stuff :P ...)
}
I compiled the quicknet3 library myself, without error, and installed it to /home/install/x86_64/lib/libquicknet3.a
So, I can't understand why the call from trapper.cpp is unable to find the reference to this constructor definition. The g++ arguments of -L/home/install/x86_64/lib -lquicknet3 should do the trick, right?
Any ideas?
Thanks,
Roy
I notice that you're mixing FILE* and _IO_FILE*. I'm not familiar with the latter, are you sure they're one and the same?
A quick workaround is to add /home/install/x86_64/lib/libquicknet3.a to g++ commandline.
I you want to investigate further, if g++ is picking another copy of libquicknet3, you can pass -v to g++ so it will output its searching paths.
FILE is a typedef of _IO_FILE. Your linker is treating it as a unique type.
You could try:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", (FILE *)fp, 1);
to see if this resolve your constructor.
(FILE is defined in stdio.h, _IO_FILE in libio.h if you're interested)
Related
I have a C++ source mycpp.cpp and a C source myc.c. The C source contains a function myCFunc(), which is called from the C++:
extern "C"
{
#include "my_c.h"
}
void aCppFunction()
{
myCFunc(stuff, and, things);
...
}
The two sources are compiled (to .o), and then archived (to .a), and then indexed, so no linking occurs:
ar qc thing.a *.o
ranlib thing.a
Later in the wider software build, this component archive is linked into a binary, and I get this error:
/usr/bin/ld: /path/to/mycpp.cpp:55: undefined reference to `myCFunc(unsigned char const*, unsigned int, unsigned int)'
I have extracted thing.a and can quite clearly see myc.c.o and mycpp.cpp.o, so I search them for the function:
> nm myc.c.o | grep myCFunc
00000000000001d0 T myCFunc
> nm -C mycpp.cpp.o | grep myCFunc
U myCFunc(unsigned char const*, unsigned int, unsigned int)
Can you see what is happening here? Why does the nm result for the C++ include the list of argument types, but the C result not? It seems to me that the function myCFunc() is defined in myc.c.o, which is part of thing.a along with mycpp.cpp.o, and that myCFunc's header is included correctly.
Please help!
The unlikely answer, based on j6t's invaluable comment:
Clearly, the caller of myCFunc does not see that name as extern "C", because the error message contains the parameter types. If it were seen as extern "C", the error message would only say undefined reference to myCFunc. – j6t
... is that what I did not show above, due to my C++ inexperience, is that the C header was included at the end of a train of other C++ headers, without using extern "C".
hope you guys are doing well. I am just getting linker error in C++ , I don't know why? Everything is correct....
Check below testing.h file
#ifndef __MYClass__
#define __MYClass__
#include<iostream>
using namespace std;
class Abc {
private:
int a;
public:
void input();
void display();
};
#endif
and here's implementation of these functions in Functions.cpp file.
#include"testing.h"
void Abc::input() {
cout<<"Enter any value : ";
cin>>a;
}
void Abc::display() {
cout<<"You Entered : "<<a;
}
And now, in main.cpp
#include<iostream>
#include"testing.h"
using namespace std;
int main() {
Abc obj;
obj.input();
obj.display();
return 0;
}
All files are compiled successfully.
In main.cpp Linker says....
g++ -Wall -o "main" "main.cpp" (in directory: /home/Welcome/C++ Practices/testingLinux)
/usr/bin/ld: /tmp/ccYI9LAy.o: in function main': main.cpp:(.text+0x10): undefined reference to Abc::input()'
/usr/bin/ld: main.cpp:(.text+0x1c): undefined reference to `Abc::display()'
collect2: error: ld returned 1 exit status
Compilation failed.
I'm using built-in linux compiler...
There are multiple ways you can fix this but before that please read up on Translation Unit.
Coming to your problem.
When you write
g++ -Wall -o main main.cpp
The compiler will pick up main.cpp for compilation and expand testing.h that includes the declaration for class ABC and with this header file it can determine what is the size of ABC and be able to generate instructions reserving space for obj on the stack. It can't see the definition for input() and display() hence defers that task to the linker. Note that testing.cpp is not in the picture at all since the compiler doesn't know that the implementation of ABC is in testing.cpp. Now when the linker tries to resolve the symbols input() it fails to find the definition for it and throws the error
undefined reference to Abc::input()
So, to fix this you can tell explicitly upfront that it also needs to take in testing.cpp while compiling main.cpp by
g++ -o main main.cpp testing.cpp
Another way is to create a dynamic library out of testing.h and testing.cpp
g++ -shared -fPIC testing.cpp -o libtest
and then link it against main.cpp
g++ -o main main.cpp -I. -L. libtest
What this does is that the compiler still can't figure out the definition of input() and display() but the linker can since now the library containing the definitions is provided to it.
You are not compiling Functions.cpp file.
This should fix your issue:
g++ main.cpp Functions.cpp
Including the following statement in my code
main_module->dump(); // main_module is of type llvm::Module*
causes the following linker error:
undefined reference to 'llvm::Module::dump() const'
The dump method resides in /usr/lib/llvm-5.0/include/llvm/IR/Module.h
I checked stack overflow (Using llvm::Function::dump(), linker gives "undefined reference to `llvm::Value::dump() const'"), and it seems we get this error when the linker isn't fed the libraries in correct order. However, I clearly have the libraries in the end in my compilation command:
clang++-5.0 -g -O3 main.cpp -o main llvm-config-5.0 --cxxflags --ldflags --system-libs --libs core mcjit native
Any help is appreciated.
The weird thing is, the linker figured out that the type of the dump method. It clearly went in the include file. So why would it call it an undefined reference?
Code I am trying to run:
`
# include "llvm/IR/LLVMContext.h"
# include "llvm/IR/Module.h"
# include "llvm/IR/IRBuilder.h"
# include <iostream>
using namespace llvm;
static LLVMContext ctxt;
static IRBuilder<> builder(ctxt);
int main(int argc, char** argv) {
Module* main_module = new Module("main_module", ctxt);
std::cout << main_module->getModuleIdentifier() << "\n";
FunctionType* func_type = FunctionType::get(builder.getInt32Ty(), false);
Function* main_func = Function::Create(func_type,Function::ExternalLinkage, "main", main_module);
if (main_module->getFunction("main")) {
std::cout << "Found function!\n";
}
main_module->dump(); // need this for debugging and testing reasons with LLVM
return 0;
}
In addition to the solution that Subrat provided, you can adjust your code to avoid calling dump. You can achieve the same thing by calling:
main_module->print(llvm::outs(), nullptr);
Similarly, if you want to dump a LLVM function, you can write:
main_func->print(llvm::outs());
Actually, as of LLVM 5.0.0, this is how the dump() function is implemented.
Seems like the definition for dump is in ASMWriter.cpp, which seems to be depracated.
Also, ASMWrite.cpp's debug method refers to dbgs() which is in debug.cpp
I fixed the problem by copying over debug.cpp and the Module::dump() (from ASMWriter.cpp--since I don't need the whole code, only a specific subroutine from this file) routine and putting it in my cpp file.
I want investigate how is it possible to link C++ program without libstdc++, but with support of rtti. I tried compile it in the way described below. Any necessary but absent symbol I can define like function strcmp in the example, but is it possible to define typeinfo symbols without explicit mangle/demangle magic? And if possible how?
cd /tmp && cat << 'eof' >rtti.cpp && g++ -nodefaultlibs -lc rtti.cpp
extern "C" int strcmp(const char *s1, const char *s2) { return 0; };
#include "typeinfo"
int main(){
return typeid(int) == typeid(char);
}
Linker says:
/tmp/cc6rBAef.o: In function `main':
rtti.cpp:(.text+0x18): undefined reference to `typeinfo for char'
rtti.cpp:(.text+0x1d): undefined reference to `typeinfo for int'
collect2: error: ld returned 1 exit status
So, how can I define 'typeinfo of char'(_ZTIc##CXXABI_1.3) in source file using g++ or clang++?
PS. Don't ask me why do I need it. Just a curiosity.
Since the symbols needed for RTTI seem to be in the libstdc++ library, you cannot do completely without it. Note that I found this by running
readelf -Ws `g++ -print-file-name=libstdc++.so` | awk '{print $8}' | c++filt | grep 'typeinfo for'
What you can do, however, is statically link with libstdc++:
g++ -static-libstdc++ rtti.cpp
In this way, you won't have any dynamic dependencies on libstdc++ and only the symbols you actually need are pulled in to your executable. (Well, all symbols from the object file that contains the needed symbols, fundamental_type_info.o in you example, I suppose.)
Thanks to gcc community for hint.
The answer is:
"gcc use some magic to substitute destructor of __fundamental_type_info to a set of typeinfo symbols"
Substitution code is placed in file: gcc-4.7.2/gcc/cp/rtti.c, void emit_support_tinfos(void);
rtti.cc:
#include <typeinfo>
namespace __cxxabiv1 {
class __fundamental_type_info:public std::type_info{
public:
explicit __fundamental_type_info(const char* __n) : std::type_info(_n) { }
virtual ~__fundamental_type_info(){};
};
}
int main(){
return typeid(int) == typeid(char);
}
All fundamental typeinfos are inserted into object file during compilation.
$g++ -c ./rtti.cc;readelf -sW ./rtti.o |c++filt|grep typeinfo|wc -l
$153
So the question is answered.
I have a header (only) file constants.h, where I define all the constant variables, to be used later in the library. However, there is one variable, which I would like to define run-time in an implementation file. I tried to do something like this:
constant.hpp
extern const unsigned int numTests;
somewhere else in run.cpp
const unsigned int numTests = 10;
and, then yet another file tester.cpp uses
if ( n < numTests) {
// do something
}
Now, when I compile it, I get a linker error in tester.o as undefined symbol numTests. I sort of understand why this is happening: the tester.cpp includes constants.hpp and not the run.cpp and so, it can not find the constant numTests initialized in run.cpp.
Is there any better way to do it?
TIA,
Nikhil
Make sure you are compiling both run.cpp and tester.cpp when you compile your program and you won't get a linker error.
You need to link run.o when creating the executable:
g++ -o tester tester.cpp run.o ; for GNU C++
(Check your own compiler's command line switches if you're not using GNU C++)