I have a project which uses the autotools build system to create a static library. I wish to test this library by making a small test program which links to it.
The test program is being created in the code::blocks IDE. The paths containing the headers have been added to the search directories, and the included library added.
When I compile my test program I get the following error:
obj/Debug/main.o: In function `givens':
<snip> undefined reference to `xhypot(double, double)'
However, xhypot is a global function declared, in an included header in real.h
as:
nr_double_t xhypot (const nr_double_t, const nr_double_t);
and defined in a companion file real.cpp
.
nr_double_t xhypot (const nr_double_t a, const nr_double_t b) {
nr_double_t c = fabs (a);
nr_double_t d = fabs (b);
if (c > d) {
nr_double_t e = d / c;
return c * sqrt (1 + e * e);
}
else if (d == 0)
return 0;
else {
nr_double_t e = c / d;
return d * sqrt (1 + e * e);
}
}
The type nr_double_t is defined in config.h as:
/* The global type of double representation. */
#define nr_double_t double
Where the offending call to xhypot
occurs is in a static helper function for a template class like so:
static nr_double_t
givens (nr_double_t a, nr_double_t b, nr_double_t& c, nr_double_t& s) {
nr_double_t z = xhypot (a, b);
c = a / z;
s = b / z;
return z;
}
However, xhypot
is also called in other non-static member functions of the class with the exact same syntax (i.e. xhypot(double,double)
and if I replace the line nr_double_t z = xhypot (a, b);
in this static method with the line nr_double_t z = 0.0;
the error disappears.
Here is the entirety of my test program:
#include "config.h"
#include "m_trsolver.h"
int main (int argc, char ** argv)
{
char infile[] = "test.net";
m_trsolver the_m_trsolver;;
return 0;
}
And the full build log:
g++ -Wall -DHAVE_CONFIG_H -g -I../qucs/qucs-core -I../qucs/qucs-core/src -I../qucs/qucs-core/src/components -I../qucs/qucs-core/src/components/devices -I../qucs/qucs-core/src/components/digital -I../qucs/qucs-core/src/components/verilog -I../qucs/qucs-core/src/components/microstrip -I../qucs/qucs-core/src/converter -I../qucs/qucs-core/src/m-interface -I../qucs/qucs-core/src/math -c /home/s0237326/src/qucs_m_interface_test/main.cpp -o obj/Debug/main.o
/home/s0237326/src/qucs_m_interface_test/main.cpp: In function ‘int main(int, char**)’:
/home/s0237326/src/qucs_m_interface_test/main.cpp:10: warning: unused variable ‘infile’
g++ -L../qucs/qucs-core -L../qucs/qucs-core/src -L../qucs/qucs-core/src/components -L../qucs/qucs-core/src/components/devices -L../qucs/qucs-core/src/components/digital -L../qucs/qucs-core/src/components/verilog -L../qucs/qucs-core/src/components/microstrip -L../qucs/qucs-core/src/converter -L../qucs/qucs-core/src/m-interface -L../qucs/qucs-core/src/math -o bin/Debug/qucs_m_interface_test obj/Debug/main.o ../qucs/qucs-core/src/libqucsatorfull.a
obj/Debug/main.o: In function `givens':
/home/s0237326/src/qucs_m_interface_test/../qucs/qucs-core/src/eqnsys.cpp:1341: undefined reference to `xhypot(double, double)'
obj/Debug/main.o: In function `main':
/home/s0237326/src/qucs_m_interface_test/main.cpp:11: undefined reference to `m_trsolver::m_trsolver()'
/home/s0237326/src/qucs_m_interface_test/main.cpp:13: undefined reference to `m_trsolver::~m_trsolver()'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 1 warnings
I'm using code::blocks 10.05 on Scientific Linux 6.1 with gcc 4.4.6 and I'm passing -DHAVE_CONFIG_H as there's lots of
#if HAVE_CONFIG_H
# include <config.h>
#endif
In the sources, with config.h
being generated by autoconf. I should also add that the code compiles fine when built as a program. I have extracted a subset of the code for this program (all but one file) to put into this static library.
The template class is spread over two files, eqnsys.h
and eqnsys.cpp
. I know it is not best practice to do this, it has probably been done as it is quite large. It is not my code. eqnsys.cpp
is included at the bottom of eqnsys.h
( #include "eqnsys.cpp"
). The static helper function is defined in eqnsys.cpp
. real.h
is #include
ed at the top of eqnsys.cpp
but not eqnsys.h
in case this is relevant. Adding the following to the top of eqnsys.cpp
:
template class eqnsys<nr_complex_t>;
template class eqnsys<nr_double_t>;
To force instantiation does not resolve the issue. If I change the givens function to be a member function instead of a static helper function the error disappears. This is the route I might take, but what is the real root of the issue so I can avoid it in future?