Search code examples
adaundefined-referencedynamic-librarygnat

Thick binding dynamic library: Undefined references


What I did so far on my Linux Mint system:

  1. Write a thin binding to the GSL library
  2. Write a thick binding based on the thin binding
  3. Write a test program for 1.
  4. Write a test program for 2.

When I create static libraries, everything works fine. When creating dynamic libraries however, compiling 4. with

gprbuild -P test_odeiv2_dyn

gets me undefined references:

Compile
   [Ada]          test_odeiv2.adb
   [Ada]          odeiv2_aux.adb
   [Ada]          integration.adb
   [Ada]          odeiv2.adb
Build Libraries
   [gprlib]       gsl.lexch
   [link library] libgsl.so
Bind
   [gprbind]      test_odeiv2.bexch
   [Ada]          test_odeiv2.ali
Link
   [link]         test_odeiv2.adb
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_driver_apply'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk4imp'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_msbdf'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_bsimp'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rkf45'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk1imp'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk4'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_driver_free'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_strerror'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rkck'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_msadams'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_driver_alloc_y_new'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk2imp'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_integration_qng'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk8pd'
/usr/bin/ld: /home/frank/Lib/Ada/Num/GSL/lib//libgsl.so: undefined reference to `gsl_odeiv2_step_rk2'
collect2: error: ld returned 1 exit status
gprbuild: link of test_odeiv2.adb failed
gprbuild: failed command was: /usr/bin/gnatgcc test_odeiv2.o b__test_odeiv2.o -L/home/frank/Lib/Ada/Num/GSL/lib/ -lgsl -L/home/frank/Lib/Ada/Num/GSL/Thin/lib/ -lgsl_thin_dyn -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas -L/home/frank/Lib/Ada/Num/Tests/Test_GSL/obj_dyn/ -L/home/frank/Lib/Ada/Num/Tests/Test_GSL/obj_dyn/ -L/home/frank/Lib/Ada/Num/GSL/lib/ -L/home/frank/Lib/Ada/Num/GSL/Thin/lib/ -L/usr/lib/gcc/x86_64-linux-gnu/9/adalib/ -shared-libgcc -lgnarl-9 -lgnat-9 -lrt -lpthread -lrt -ldl -Wl,-rpath-link,/usr/lib/gcc/x86_64-linux-gnu/9//adalib -Wl,-z,origin,-rpath,$ORIGIN/../..//GSL/lib:$ORIGIN/../..//GSL/Thin/lib:/usr/lib/x86_64-linux-gnu:$ORIGIN//obj_dyn:/usr/lib/gcc/x86_64-linux-gnu/9/adalib:/usr/lib64:/usr/lib -o /home/frank/Lib/Ada/Num/Tests/Test_GSL//test_odeiv2_dyn

What am I missing?

My project files are:

1.

library project GSL_Thin_Dyn is

   version:= "1";

   for Source_Dirs use ("src", "src/matrix");
   for Library_Dir use "lib";
   for Object_Dir use "obj_rel";
   for Library_Name use "gsl_thin_dyn";
   for Library_Kind use "relocatable";
   for Library_Version use "libgsl_thin.so." & version;
   for Externally_Built use "false";

   package Linker is
      for Linker_Options use ("-L/usr/lib/x86_64-linux-gnu", "-lgsl", "-lgslcblas");
   end Linker;

end GSL_Thin_Dyn;
with "Thin/gsl_thin_dyn";

library project GSL_dyn is

   version:= "1";
   
   for Source_Dirs use (".");
   for Object_Dir use "obj_dyn";
   for Library_Dir use "lib";
   for Library_Name use "gsl";
   for Library_Kind use "relocatable";
   for Library_Version use "libgsl.so." & version;
   for Externally_Built use "false";

   package Linker is
      for Linker_Options use ("-L/usr/lib/x86_64-linux-gnu", "-lgsl", "-lgslcblas");
   end Linker;

end GSL_dyn;
with "../../../Gen/gen_shared";
with "../../GSL/Thin/gsl_thin_dyn";

project Test_Odeiv2_Thin_Dyn is

   for Source_Dirs use (".");
   case gen_shared.mode is
      when "debug"  => for Object_Dir use "obj_dyn";
      when "release"    => for Object_Dir use "obj_dyn/release";
      when others   => null;
   end case;
   for Exec_Dir use ".";
   for Main use ("test_odeiv2_thin.adb");

   package Builder is
      for Executable ("test_odeiv2_thin.adb") use "test_odeiv2_thin_dyn";
   end Builder;

end Test_Odeiv2_Thin_Dyn;
with "../../../Gen/gen_shared";
with "../../GSL/gsl_dyn";
        
project Test_Odeiv2_Dyn is
        
   for Source_Dirs use (".");
   case gen_shared.mode is
      when "debug"  => for Object_dir use "obj_dyn";
      when "release"    => for Object_Dir use "obj_dyn/release";
   end case;
   for Exec_Dir use ".";
   for Main use ("test_odeiv2.adb");
        
   package Linker is
      for Linker_Options use ("-L/usr/lib/x86_64-linux-gnu", "-lgsl", "-lgslcblas");
   end Linker;
    
   package Builder is
     for Executable ("test_odeiv2.adb") use "test_odeiv2_dyn";
   end Builder;
        
end Test_Odeiv2_Dyn;

Solution

  • You named your thick wrapper library gsl. The library you're wrapping is also named gsl. Internally, this will cause the linker to get -lgsl two times, and both will be resolved to your thick wrapper. This is why it's missing the symbols from the original library.

    Change the Library_Name of your thick wrapper to resolve this.