Why does gsl-library not compile/link in 11.10, despite that it did under 11.04 with the same makefile and program?
I have a problem with the gsl library in Oneiric - after upgrade from Natty to Oneiric I cannot build a program anymore with my own makefile, despite the fact that in QT Creator everything works fine and the program compiles with no problems. The necessary flags for the gsl libraries are set in both makefiles and on Natty both ways of compiling the program worked well. The gsl library files are all installed.
EDIT: the original code I tried to compile is written in c++, which is the reason that I use g++ also with the test.c file
This is the error message:
user@user:~$ g++ -lgsl -lgslcblas -lm /home/user/test.c
/home/user/test.c: In function ‘int main()’:
/home/user/test.c:92:24: warning: format ‘%d’ expects argument of type ‘int’, but
argument 2 has type ‘size_t {aka long unsigned int}’ [-Wformat]
/tmp/ccOLKTZH.o: In function `my_f(gsl_vector const*, void*)':
test.c:(.text+0x25): undefined reference to `gsl_vector_get'
test.c:(.text+0x3b): undefined reference to `gsl_vector_get'
/tmp/ccOLKTZH.o: In function `my_df(gsl_vector const*, void*, gsl_vector*)':
test.c:(.text+0xf7): undefined reference to `gsl_vector_get'
test.c:(.text+0x10d): undefined reference to `gsl_vector_get'
test.c:(.text+0x14c): undefined reference to `gsl_vector_set'
test.c:(.text+0x18a): undefined reference to `gsl_vector_set'
/tmp/ccOLKTZH.o: In function `main':
test.c:(.text+0x26b): undefined reference to `gsl_vector_alloc'
test.c:(.text+0x288): undefined reference to `gsl_vector_set'
test.c:(.text+0x2a1): undefined reference to `gsl_vector_set'
test.c:(.text+0x2a8): undefined reference to `gsl_multimin_fdfminimizer_conjugate_fr'
test.c:(.text+0x2bd): undefined reference to `gsl_multimin_fdfminimizer_alloc'
test.c:(.text+0x2e8): undefined reference to `gsl_multimin_fdfminimizer_set'
test.c:(.text+0x2f9): undefined reference to `gsl_multimin_fdfminimizer_iterate'
test.c:(.text+0x31e): undefined reference to `gsl_multimin_test_gradient'
test.c:(.text+0x357): undefined reference to `gsl_vector_get'
test.c:(.text+0x374): undefined reference to `gsl_vector_get'
test.c:(.text+0x3ca): undefined reference to `gsl_multimin_fdfminimizer_free'
test.c:(.text+0x3d6): undefined reference to `gsl_vector_free'
collect2: ld returned 1 exit status
This is the file I used for testing purposes:
#include <gsl/gsl_multimin.h>
/* Paraboloid centered on (p[0],p[1]), with
scale factors (p[2],p[3]) and minimum p[4] */
double
my_f (const gsl_vector *v, void *params)
{
double x, y;
double *p = (double *)params;
x = gsl_vector_get(v, 0);
y = gsl_vector_get(v, 1);
return p[2] * (x - p[0]) * (x - p[0]) +
p[3] * (y - p[1]) * (y - p[1]) + p[4];
}
/* The gradient of f, df = (df/dx, df/dy). */
void
my_df (const gsl_vector *v, void *params,
gsl_vector *df)
{
double x, y;
double *p = (double *)params;
x = gsl_vector_get(v, 0);
y = gsl_vector_get(v, 1);
gsl_vector_set(df, 0, 2.0 * p[2] * (x - p[0]));
gsl_vector_set(df, 1, 2.0 * p[3] * (y - p[1]));
}
/* Compute both f and df together. */
void
my_fdf (const gsl_vector *x, void *params,
double *f, gsl_vector *df)
{
*f = my_f(x, params);
my_df(x, params, df);
}
int
main (void)
{
size_t iter = 0;
int status;
const gsl_multimin_fdfminimizer_type *T;
gsl_multimin_fdfminimizer *s;
/* Position of the minimum (1,2), scale factors
10,20, height 30. */
double par[5] = { 1.0, 2.0, 10.0, 20.0, 30.0 };
gsl_vector *x;
gsl_multimin_function_fdf my_func;
my_func.n = 2;
my_func.f = my_f;
my_func.df = my_df;
my_func.fdf = my_fdf;
my_func.params = par;
/* Starting point, x = (5,7) */
x = gsl_vector_alloc (2);
gsl_vector_set (x, 0, 5.0);
gsl_vector_set (x, 1, 7.0);
T = gsl_multimin_fdfminimizer_conjugate_fr;
s = gsl_multimin_fdfminimizer_alloc (T, 2);
gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.01, 1e-4);
do
{
iter++;
status = gsl_multimin_fdfminimizer_iterate (s);
if (status)
break;
status = gsl_multimin_test_gradient (s->gradient, 1e-3);
if (status == GSL_SUCCESS)
printf ("Minimum found at:\n");
printf ("%5d %.5f %.5f %10.5f\n", iter,
gsl_vector_get (s->x, 0),
gsl_vector_get (s->x, 1),
s->f);
}
while (status == GSL_CONTINUE && iter < 100);
gsl_multimin_fdfminimizer_free (s);
gsl_vector_free (x);
return 0;
}
I've just run into the same problem after upgrading to Oneiric (except with c++ code instead of c code). The problem shows up with g++-4.6 and 4.5, but compiling with g++-4.4 works as it did in Natty. So I suspect it's a compiler bug of some sort, but reverting to 4.4 seems to be feasible workaround for now.
EDIT: There is no need to downgrade - here's the root cause: It turns out this happens with any attempt to link in the wrong order because gcc on Oneiric now uses the --as-needed flag. The solution is to change the order of parameters to the linker, see http://ubuntuforums.org/archive/index.php/t-1833136.html . This change is explained in http://wiki.debian.org/ToolChain/DSOLinking; Fedora uses this as well.