I have a library (technically a Ruby extension) called NMatrix which is written in C and C++. It uses C++ templates to manage different types, e.g., Rational128 versus Rational64. It also has RubyObject and Complex64 and Complex128. I force these template versions to be built by creating some inside an object file -- in a function that is called from the library entry point.
It works just fine in GCC 4.7, but when I compile on Travis-CI, it encounters an undefined symbol error at run-time:
exposes cblas rot /home/travis/.rvm/rubies/ruby-2.0.0-p247/bin/ruby: symbol lookup error: /home/travis/build/SciRuby/nmatrix/lib/nmatrix.so: undefined symbol: _ZN2nm7ComplexIfEC1ERKNS_10RubyObjectE
The undefined symbol is nm::Complex::Complex(nm::RubyObject const&), which is explicitly defined and instantiated (see below).
Here's a pared down version of data.cpp:
#include "data.h"
void nm_init_data() { // called from library entry point
// These force the compiler to build these versions of the typedef'd templates.
// I think this is a gross way to do it, but can't find a better idea.
nm::RubyObject obj(INT2FIX(1));
nm::Rational32 x(obj);
nm::Rational64 y(obj);
nm::Rational128 z(obj);
nm::Complex64 a(obj); // Clear instantiation of the undefined symbol
nm::Complex128 b(obj);
}
and data.h like so:
#include "nmatrix.h"
#include "complex.h" // classes are all declared in headers
#include "rational.h"
#include "ruby_object.h"
void nm_init_data();
nmatrix.cpp is where the library entry point is declared. The relevant parts look like this:
void Init_nmatrix() {
// declarations of Ruby-exposed functions here, e.g.,
rb_define_method(cNMatrix, "initialize", (METHOD)nmatrix_constructor, -1);
nm_init_data();
}
So what am I doing wrong? Why does this work on GCC 4.7.1 (all specs pass), but not 4.6.3? Is it a bug? (If it's a bug, is there a work-around?)
If you're curious, the full versions of the relevant files are here.
Related
I'm trying to compile/port an older version of OpenOffice. It uses Boost v1.34.1, which is part of the source tree. The error message is as follows:
Undefined symbols:
"boost::throw_exception(std::exception const&)", referenced from:
boost::detail::shared_count::shared_count<ScToken>(ScToken*)in detfunc.o
ld: symbol(s) not found
Boost is new to me, and I haven't been able to find much online to help me understand this. From the error message, I understand that I probably need to link a library. However, boost::throw_exception is defined in a header file with no matching library (that I can find). Just for kicks, I've tried #include <boost/throw_exception.hpp> in detfunc and using symbolic links to put the header file in the same directory with no luck.
Is there a library I should be linking with -l or an include path with -I? How should I get that symbol referenced in?
Boost expects the project either to be built with macro BOOST_NO_EXCEPTIONS undefined, or to define the function boost::throw_exception itself.
From <boost/throw_exception.hpp> in version 1.34.1:
namespace boost
{
#ifdef BOOST_NO_EXCEPTIONS
void throw_exception(std::exception const & e); // user defined
#else
//[Not user defined --Dynguss]
template<class E> inline void throw_exception(E const & e)
{
throw e;
}
#endif
} // namespace boost
Boost's configuration headers will determine whether to define the macro or not. It looks like it boils down to the compiler you're using, but there may be other factors. Take a look in the boost/config/compiler/ folder for the header file that corresponds to your compiler, then search for BOOST_NO_EXCEPTIONS in it. There should be some conditions around the #define to help explain when Boost defines it. You may be able to configure your build to avoid the definition and get past the linker error you're experiencing.
If you're unable to change your compiler config to avoid the definition, then you're probably left defining boost::throw_exception(std::exception const & e) yourself somewhere in the OpenOffice code. I'm unfamiliar with that code, though, so I can't give a good suggestion where it should go.
I am getting nuts with this error so I thought some of more experienced developers can help me in this regard.
I am trying to compile a sample project which uses a C++ library (named Poco). My project is linked to compiled poco libraries.
Below is my (most simplified) code:
#include "Poco/UUID.h"
class x
{
void func1()
{
new Poco::UUID(); //A
}
};
void func1()
{
new Poco::UUID(); //B
}
Now when above code is compiled, line 'A' has no error but for line 'B' linker says:
undefined reference to `Poco::UUID::UUID()'
What is the reason? When I instantiate a class from external lib in a class method no error occurs but the same code in a function produces linker error? (When I comment line B, no error occurs and linker output files are generated)
My configuration: Win7/g++/CodeLite/MinGW-4.7.1
*Update 2:*Thanks. My problem is now resolved and the issue is that I had compiled library using MSVC compiler while my application was being compiled using g++ (both under Windows platform). So I re-compiled library using g++ and everything works fine now.
Update 1: here is my IDE's output when I build my project:
C:\Windows\system32\cmd.exe /c "mingw32-make.exe -j 4 -e -f "dll1.mk" all"
----------Building project:[ dll1 - Debug ]----------
g++ -shared -fPIC -o ./Debug/dll1.so #"dll1.txt" -L. -Lc:/poco/lib -lPocoFoundationd
./Debug/PluginLibrary.o: In function `Z5func1v':
C:/Users/PARS/Documents/codelite/workspace1/dll1/PluginLibrary.cpp:12: undefined reference to `Poco::UUID::UUID()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Debug/dll1.so] Error 1
dll1.mk:77: recipe for target `Debug/dll1.so' failed
1 errors, 0 warnings
Your member function x::func1() is never ODR-used in that compilation unit (source file). Most compilers only generate compiled code for a member function defined inside the class definition if that member function is ODR-used within the compilation unit that is being compiled. Suppose some other source file does use x::func1(). If you compile that other source file, the compiler will produce object code for x::func1() in the object file that corresponds to that other source file.
The compiler can get away with bypassing the process of generating compiled code for x::func1() here because the class definition has to be the same across all compilation units. If you compile some other source file that has a different definition of class x you have violated the one definition rule. This is undefined behavior and no diagnosis is required.
If no source file uses x::func1() you have some dead code that just never happens to be compiled. The code has an error but it's never detected.
The compiler cannot get away with bypassing generating compiled code for the free function func1(). This function has external linkage; there's no way the compiler can tell if it might be used somewhere else. The compiler must generate compiled code for that free function.
Here's a minimum working example:
class Missing {
public:
Missing();
int value;
};
class UsesMissing {
public:
int use_missing () {
Missing missing;
return missing.value;
}
int dont_use_missing () {
return 0;
}
};
#ifdef DEFINE_USE_MISSING
int use_missing () {
Missing missing;
return missing.value;
}
#endif
int main () {
UsesMissing test;
#ifdef USE_MISSING
return test.use_missing();
#else
return test.dont_use_missing();
#endif
}
Compile with neither DEFINE_USE_MISSING or USE_MISSING defined and this compiles and links just fine with g++ and clang++. Define either one of those flags and the file fails in the link step because of the undefined reference Missing::Missing().
You should link with the correct library to fix your link (see Poco docu for the correct one).
func1 has extern linkage and so linker need Poco::UUID
whereas X::func1 is inline/private/unused.
if you use static foo1() or inline foo1() the linker error disappears
if you use x::func1 or implement x::func1 outside of the class x{}; the error linker appears
Edit: I have updated my question with changes I've made, upon answers.
I'm trying to link to a little library that I've wrote to learn ho this is done with C++ with no luck. G++ is complaining with undefined reference.
The root directory of library I want to link is in directory ~/code/gklib/cxx/. The structure of this directory is as follows:
~/code/gklib/cxx/
|
|`-> gk.{hh,cc}
|`-> libgk.o
|
`-> lib/
|
`-> libgk.a
I have compiled gk.cc with -c flag, then transformed the resulting object file to a .a file with ar rvsc lib/libgk.a libgk.o.
The client to this library is at folder ~/code/cpp. In this directory I compiled some_stuff.cc to an object file again, then I tried to link to it with this command:
$ cxx some_stuff.o -L../gklib/cxx/lib -lgk -o some_stuff
I get this error:
some_stuff.o: In function `main':
some_stuff.cc:(.text+0x49): undefined reference to `void GK::algorithms::insertionSort<int, 5ul>(int*)'
collect2: error: ld returned 1 exit status
These are contents of these files:
~/code/cpp/some_stuff.cc
#include <cstdlib>
#include <iostream>
#include <gk.hh>
using namespace std;
int main(int argc, char **argv) {
int i = -1;
int arr[5] = { 3, 4, 2, 1, 5 };
const size_t len = sizeof(arr)/sizeof(int);
GK::algorithms::insertionSort<int, len>(arr);
while(++i < 5)
cout << arr[i] << " ";
cout << endl;
exit(EXIT_SUCCESS);
}
~/code/gklib/cxx/gk.cc
#include "gk.hh"
template<class T, size_t len>
void GK::algorithms::insertionSort(T arr[len]){
// insertion sort
}
~/code/gklib/cxx/gk.hh
#pragma once
#include <cstdlib>
#define NAMESPACE(ns) namespace ns {
#define END_NAMESPACE(ns) }
NAMESPACE(GK)
NAMESPACE(algorithms)
template<class T, size_t len>
extern void insertionSort(T arr[len]);
END_NAMESPACE(algorithms)
END_NAMESPACE(GK)
I've tried many variations on my commands with no result. Internet is full of tutorials and forums with instructions those did not work for me. This code ran perfectly when all the stuff was in one file. How can I resolve this problem? Thanks in advance.
I think it's more something like:
cxx some_stuff.o -L$HOME/gklib/cxx/lib -B../gklib/cxx/lib -lgklib -o some_stuff
-lgklib, not -Igklib (-I option specify an include folder)
but you'll have to rename your gklib.a by libgklib.a
Maybe you can even remove -B../gklib/cxx/lib, just try it out :)
I see several problems: in order:
If this is your exact command line, the -L option doesn't
point to the structure you've shown above (where there is no
cxx in the path).
I don't know why you're using -B. This tells the compiler
where to look for its libraries, etc. Normally, this is only
necessary when you want to test parts of the compiler you've
modified.
I don't see where you've specified to link against the
library. Since the library doesn't respect the usual naming
conventions (libname.a), you'll have to
specify it directly (in the same way you'd specify an object
file), and the -L option isn't used. Alternatively, you name
it libgk.a, or something like that, and add a -lgk to the
command line, after your object files.
Finally, the error messages refer to an instantiation of
a template. This typically occurs because the implementation of
the template is in a source file, not in the header. The
standard requires that the implementation be visible when it
triggers the instantiation of a template. The way g++ (and
almost every other compiler) works is that if the implementation
isn't visible, they suppose that the template will be
instantiated in another translation unit, and output external
references to it. But if the implementation is in a source,
there will be no instantiation, and you'll get a linker error.
(You'll also not find the assembler for the instantiation
anywhere, either, because the template hasn't been
instantiated.) You should include the source code at the bottom
of your header, and not compile it separately.
I have solved this problem, with the help of this and this questions. The problem lies in the fact that void insertionSort(T *) is a template function, and template functions can only be implemented in header files. The reason for this is, the compiler needs to reach the definition of the to create a new function for each call to it with a different type as the argument to template. I have moved the definition of this function to gk.h, which resulted in a successfull compilation and linkage.
What is the simplest to use c++ library that graphs functions like matlab and octave do? I have looked over several and have found similar major problems with all of them: i cannot compile an empty program that only has
#include <iostream>
#include "header_to_include.h"
int main(){
return 0;
}
i have found koolplot, some wxwidget stuff, sdl_graph, gnuplot++, and something with Qt. ive looked at some of the ones on the list here, but some are for other languages while others use installers or depended on other programs. When I got files extracted and tried compiling my simple code or given example code from within the download, codeblocks always complains about missing headers or variables or some other things.
i would use gnuplot, except i dont want to create gnuplot files from my cpp files, even if its through a pipe. i want to be able to graph straight from the program.
is there nothing that is simply a handful of files in a zip that can be extracted and used in moments rather than having to figure out which files to include, installing/downloading other major libraries, etc?
edit:
for example, i found http://sdl-grapher.googlecode.com/svn/trunk/ and downloaded the files. i already have sdl, so i copied sdlgraph.h into the includes folder and left a copy in the same directory as example.c. when i compile, i find that for some reason, #include <sdlgraph.h> doesnt work. also the int main() has no arguments despite being a SDL program. after fixing that up, i get undefined reference to 15 different functions that i can clearly see in the sdlgraph.h file such as init_graph and draw_grid
About your errors:
Since you're very new to C++ I'll explain your undefined reference errors.
In C++ you can declare a function like this:
void foo();
However, since it's declared, it doesn't main it's defined. Definitions can exist in C++ source file, libraries but also headers.
Defining the previous example:
void foo() {
std::cout << "void foo() has been called." << std::endl;
}
The error you get means that those functions just aren't defined.
I quess you have to link your application with the SDL libraries.
For more info see:
http://content.gpwiki.org/index.php/SDL:Tutorials:Setup
For more info about dynamic and static linking see:
http://www.learncpp.com/cpp-tutorial/a1-static-and-dynamic-libraries/
Hope it helps!
Whenever I compile something that #includes a user-defined class, I get these compilation errors that always look like: main.cpp: undefined reference to Complex::Complex(double, double)
I've reduced the problem to a set of three extremely bare files: main.cpp, and for example, Complex.h and Complex.cpp. I still get undefined reference errors. I'm developing in Code::Blocks on Windows but I get the same thing using g++ in Ubuntu. Why does this happen? I've tried building Complex.cpp before main.cpp in Code::Blocks, and I've tried g++ main.cpp Complex.cpp as much as I've tried just g++ main.cpp. Same errors every time.
/*======== main.cpp ========*/
#include "Complex.h"
int main()
{
Complex A(1.0, 1.0);
return 0;
}
/*======== Complex.h ========*/
#ifndef _COMPLEX_H
#define _COMPLEX_H
class Complex
{
public:
double x, y;
Complex(double real, double imag);
};
#endif
/*======== Complex.cpp ========*/
#include "Complex.h"
Complex::Complex(double real, double imag)
{
x = real;
y = imag;
}
ed: now I get different errors so I must be doing something completely wrong. Using the same code as above, I get:
main.cpp: in function 'int main()':
main.cpp:5:5: error: 'Complex' was not declared in this scope
main.cpp:5:13: error: expected ';' before 'A'
This is bizarre. Everything worked earlier when I had the class in a .cpp file, but that's "bad practice" so I moved my class definitions into .h files and kept the implementation in .cpp files, and now nothing works.
That's not a compilation error, it's a link error. You need to make sure to link all of your objects together. You can do that in a couple ways:
g++ main.cpp Complex.cpp
Should work fine (and does here when I tried with your example). You can also do it in steps:
g++ -c main.cpp
g++ -c Complex.cpp
g++ main.o Complex.o
While we are left in the dark whether this is the actual code (probably not as it works for several others), let's comment on the code itself a bit... (this won't have any effect on the linker error)
Names starting with an underscore followed by a capital letter, e.g. _COMPLEX_H, are reserved for the implementation of the C++ compiler and the C++ standard library. Don't use them.
Member variables are best made private. There is rarely any need to make actual data member public (sometimes it is reasonable to make non-function members public, e.g. an event class where users can subscribe callbacks, but these typically behave like functions although they are technically objects).
Initialization is best done in the member initializer list. That is, the constructor would look something like this:
Complex::Complex(double real, double image):
x(real),
y(imag)
{
}
Finally, to venture a few guesses what is going wrong with the actual code to cause the linking problem:
The constructor is defined to be inline. Obviously, this won't work unless the definition is visible where the constructor is used.
The declaration of Complex somehow made it into an unnamed namespace and thus the definition happens to define a different class than the one seen by main.cpp.