问题
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.
来源:https://stackoverflow.com/questions/19055501/travis-ci-fails-on-symbol-lookup-error-works-fine-elsewhere